From 61aa5880d31c05ec49b0df1fe9f1feb928311f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ken-H=C3=A5vard=20Lieng?= Date: Mon, 25 May 2015 04:00:21 +0200 Subject: [PATCH] Add config file, handle it with Viper, add a command to open it in an editor --- Godeps/Godeps.json | 73 +- .../src/github.com/BurntSushi/toml/.gitignore | 5 + .../github.com/BurntSushi/toml/.travis.yml | 12 + .../src/github.com/BurntSushi/toml/COMPATIBLE | 3 + .../src/github.com/BurntSushi/toml/COPYING | 14 + .../src/github.com/BurntSushi/toml/Makefile | 19 + .../src/github.com/BurntSushi/toml/README.md | 220 ++ .../toml/cmd/toml-test-decoder/COPYING | 14 + .../toml/cmd/toml-test-decoder/README.md | 14 + .../toml/cmd/toml-test-decoder/main.go | 90 + .../toml/cmd/toml-test-encoder/COPYING | 14 + .../toml/cmd/toml-test-encoder/README.md | 14 + .../toml/cmd/toml-test-encoder/main.go | 131 + .../BurntSushi/toml/cmd/tomlv/COPYING | 14 + .../BurntSushi/toml/cmd/tomlv/README.md | 22 + .../BurntSushi/toml/cmd/tomlv/main.go | 61 + .../src/github.com/BurntSushi/toml/decode.go | 492 +++ .../github.com/BurntSushi/toml/decode_meta.go | 122 + .../github.com/BurntSushi/toml/decode_test.go | 950 ++++++ .../src/github.com/BurntSushi/toml/doc.go | 27 + .../src/github.com/BurntSushi/toml/encode.go | 551 ++++ .../github.com/BurntSushi/toml/encode_test.go | 542 ++++ .../BurntSushi/toml/encoding_types.go | 19 + .../BurntSushi/toml/encoding_types_1.1.go | 18 + .../src/github.com/BurntSushi/toml/lex.go | 874 ++++++ .../src/github.com/BurntSushi/toml/parse.go | 498 +++ .../github.com/BurntSushi/toml/session.vim | 1 + .../github.com/BurntSushi/toml/type_check.go | 91 + .../github.com/BurntSushi/toml/type_fields.go | 241 ++ .../github.com/armon/consul-api/.gitignore | 23 + .../src/github.com/armon/consul-api/LICENSE | 362 +++ .../src/github.com/armon/consul-api/README.md | 42 + .../src/github.com/armon/consul-api/acl.go | 140 + .../github.com/armon/consul-api/acl_test.go | 140 + .../src/github.com/armon/consul-api/agent.go | 272 ++ .../github.com/armon/consul-api/agent_test.go | 162 + .../src/github.com/armon/consul-api/api.go | 323 ++ .../github.com/armon/consul-api/api_test.go | 126 + .../github.com/armon/consul-api/catalog.go | 181 ++ .../armon/consul-api/catalog_test.go | 219 ++ .../src/github.com/armon/consul-api/event.go | 104 + .../github.com/armon/consul-api/event_test.go | 37 + .../src/github.com/armon/consul-api/health.go | 136 + .../armon/consul-api/health_test.go | 98 + .../src/github.com/armon/consul-api/kv.go | 219 ++ .../github.com/armon/consul-api/kv_test.go | 374 +++ .../github.com/armon/consul-api/session.go | 204 ++ .../armon/consul-api/session_test.go | 190 ++ .../src/github.com/armon/consul-api/status.go | 43 + .../armon/consul-api/status_test.go | 31 + .../coreos/go-etcd/etcd/add_child.go | 23 + .../coreos/go-etcd/etcd/add_child_test.go | 73 + .../github.com/coreos/go-etcd/etcd/client.go | 481 +++ .../coreos/go-etcd/etcd/client_test.go | 108 + .../github.com/coreos/go-etcd/etcd/cluster.go | 37 + .../coreos/go-etcd/etcd/compare_and_delete.go | 34 + .../go-etcd/etcd/compare_and_delete_test.go | 46 + .../coreos/go-etcd/etcd/compare_and_swap.go | 36 + .../go-etcd/etcd/compare_and_swap_test.go | 57 + .../github.com/coreos/go-etcd/etcd/debug.go | 55 + .../coreos/go-etcd/etcd/debug_test.go | 28 + .../github.com/coreos/go-etcd/etcd/delete.go | 40 + .../coreos/go-etcd/etcd/delete_test.go | 81 + .../github.com/coreos/go-etcd/etcd/error.go | 49 + .../src/github.com/coreos/go-etcd/etcd/get.go | 32 + .../coreos/go-etcd/etcd/get_test.go | 131 + .../github.com/coreos/go-etcd/etcd/member.go | 30 + .../coreos/go-etcd/etcd/member_test.go | 71 + .../github.com/coreos/go-etcd/etcd/options.go | 72 + .../coreos/go-etcd/etcd/requests.go | 403 +++ .../coreos/go-etcd/etcd/requests_test.go | 22 + .../coreos/go-etcd/etcd/response.go | 89 + .../coreos/go-etcd/etcd/set_curl_chan_test.go | 42 + .../coreos/go-etcd/etcd/set_update_create.go | 137 + .../go-etcd/etcd/set_update_create_test.go | 241 ++ .../github.com/coreos/go-etcd/etcd/version.go | 6 + .../github.com/coreos/go-etcd/etcd/watch.go | 103 + .../coreos/go-etcd/etcd/watch_test.go | 119 + .../src/github.com/kr/pretty/.gitignore | 4 + .../src/github.com/kr/pretty/License | 21 + .../src/github.com/kr/pretty/Readme | 9 + .../src/github.com/kr/pretty/diff.go | 158 + .../src/github.com/kr/pretty/diff_test.go | 74 + .../src/github.com/kr/pretty/example_test.go | 20 + .../src/github.com/kr/pretty/formatter.go | 337 ++ .../github.com/kr/pretty/formatter_test.go | 261 ++ .../src/github.com/kr/pretty/pretty.go | 98 + .../src/github.com/kr/pretty/zero.go | 41 + .../_workspace/src/github.com/kr/text/License | 19 + .../_workspace/src/github.com/kr/text/Readme | 3 + .../src/github.com/kr/text/colwriter/Readme | 5 + .../github.com/kr/text/colwriter/column.go | 147 + .../kr/text/colwriter/column_test.go | 90 + .../_workspace/src/github.com/kr/text/doc.go | 3 + .../src/github.com/kr/text/indent.go | 74 + .../src/github.com/kr/text/indent_test.go | 119 + .../src/github.com/kr/text/mc/Readme | 9 + .../src/github.com/kr/text/mc/mc.go | 62 + .../_workspace/src/github.com/kr/text/wrap.go | 86 + .../src/github.com/kr/text/wrap_test.go | 44 + .../magiconair/properties/.gitignore | 2 + .../magiconair/properties/.travis.yml | 5 + .../github.com/magiconair/properties/LICENSE | 25 + .../magiconair/properties/README.md | 117 + .../magiconair/properties/benchmark_test.go | 22 + .../github.com/magiconair/properties/doc.go | 135 + .../magiconair/properties/example_test.go | 93 + .../github.com/magiconair/properties/lex.go | 409 +++ .../github.com/magiconair/properties/load.go | 124 + .../magiconair/properties/load_test.go | 137 + .../magiconair/properties/parser.go | 95 + .../magiconair/properties/properties.go | 698 +++++ .../magiconair/properties/properties_test.go | 846 +++++ .../magiconair/properties/rangecheck.go | 31 + .../mitchellh/mapstructure/.travis.yml | 7 + .../github.com/mitchellh/mapstructure/LICENSE | 21 + .../mitchellh/mapstructure/README.md | 46 + .../mitchellh/mapstructure/decode_hooks.go | 151 + .../mapstructure/decode_hooks_test.go | 229 ++ .../mitchellh/mapstructure/error.go | 34 + .../mitchellh/mapstructure/mapstructure.go | 735 +++++ .../mapstructure_benchmark_test.go | 243 ++ .../mapstructure/mapstructure_bugs_test.go | 47 + .../mapstructure_examples_test.go | 203 ++ .../mapstructure/mapstructure_test.go | 922 ++++++ .../src/github.com/spf13/cast/.gitignore | 23 + .../src/github.com/spf13/cast/LICENSE | 21 + .../src/github.com/spf13/cast/README.md | 72 + .../src/github.com/spf13/cast/cast.go | 68 + .../src/github.com/spf13/cast/cast_test.go | 117 + .../src/github.com/spf13/cast/caste.go | 378 +++ .../spf13/jwalterweatherman/.gitignore | 22 + .../spf13/jwalterweatherman/LICENSE | 21 + .../spf13/jwalterweatherman/README.md | 158 + .../spf13/jwalterweatherman/jww_test.go | 56 + .../thatswhyyoualwaysleaveanote.go | 183 ++ .../src/github.com/spf13/viper/.gitignore | 23 + .../src/github.com/spf13/viper/.travis.yml | 9 + .../src/github.com/spf13/viper/LICENSE | 21 + .../src/github.com/spf13/viper/README.md | 440 +++ .../src/github.com/spf13/viper/util.go | 198 ++ .../src/github.com/spf13/viper/viper.go | 997 ++++++ .../src/github.com/spf13/viper/viper_test.go | 553 ++++ .../xordataexchange/crypt/backend/backend.go | 32 + .../crypt/backend/consul/consul.go | 87 + .../crypt/backend/etcd/etcd.go | 84 + .../crypt/backend/mock/mock.go | 61 + .../xordataexchange/crypt/config/README.md | 86 + .../xordataexchange/crypt/config/config.go | 201 ++ .../crypt/config/config_test.go | 257 ++ .../crypt/encoding/secconf/keyring_test.go | 95 + .../crypt/encoding/secconf/secconf.go | 68 + .../crypt/encoding/secconf/secconf_test.go | 28 + .../src/golang.org/x/crypto/cast5/cast5.go | 526 ++++ .../golang.org/x/crypto/cast5/cast5_test.go | 106 + .../x/crypto/openpgp/armor/armor.go | 219 ++ .../x/crypto/openpgp/armor/armor_test.go | 95 + .../x/crypto/openpgp/armor/encode.go | 160 + .../x/crypto/openpgp/canonical_text.go | 59 + .../x/crypto/openpgp/canonical_text_test.go | 52 + .../x/crypto/openpgp/clearsign/clearsign.go | 366 +++ .../openpgp/clearsign/clearsign_test.go | 187 ++ .../x/crypto/openpgp/elgamal/elgamal.go | 122 + .../x/crypto/openpgp/elgamal/elgamal_test.go | 49 + .../x/crypto/openpgp/errors/errors.go | 72 + .../src/golang.org/x/crypto/openpgp/keys.go | 624 ++++ .../golang.org/x/crypto/openpgp/keys_test.go | 216 ++ .../x/crypto/openpgp/packet/compressed.go | 123 + .../crypto/openpgp/packet/compressed_test.go | 41 + .../x/crypto/openpgp/packet/config.go | 88 + .../x/crypto/openpgp/packet/encrypted_key.go | 168 + .../openpgp/packet/encrypted_key_test.go | 125 + .../x/crypto/openpgp/packet/literal.go | 89 + .../x/crypto/openpgp/packet/ocfb.go | 143 + .../x/crypto/openpgp/packet/ocfb_test.go | 46 + .../openpgp/packet/one_pass_signature.go | 73 + .../x/crypto/openpgp/packet/opaque.go | 161 + .../x/crypto/openpgp/packet/opaque_test.go | 67 + .../x/crypto/openpgp/packet/packet.go | 538 ++++ .../x/crypto/openpgp/packet/packet_test.go | 255 ++ .../x/crypto/openpgp/packet/private_key.go | 310 ++ .../crypto/openpgp/packet/private_key_test.go | 64 + .../x/crypto/openpgp/packet/public_key.go | 687 +++++ .../crypto/openpgp/packet/public_key_test.go | 202 ++ .../x/crypto/openpgp/packet/public_key_v3.go | 275 ++ .../openpgp/packet/public_key_v3_test.go | 82 + .../x/crypto/openpgp/packet/reader.go | 76 + .../x/crypto/openpgp/packet/signature.go | 674 ++++ .../x/crypto/openpgp/packet/signature_test.go | 42 + .../x/crypto/openpgp/packet/signature_v3.go | 146 + .../openpgp/packet/signature_v3_test.go | 92 + .../openpgp/packet/symmetric_key_encrypted.go | 164 + .../packet/symmetric_key_encrypted_test.go | 102 + .../openpgp/packet/symmetrically_encrypted.go | 290 ++ .../packet/symmetrically_encrypted_test.go | 123 + .../x/crypto/openpgp/packet/userattribute.go | 91 + .../openpgp/packet/userattribute_test.go | 109 + .../x/crypto/openpgp/packet/userid.go | 160 + .../x/crypto/openpgp/packet/userid_test.go | 87 + .../src/golang.org/x/crypto/openpgp/read.go | 427 +++ .../golang.org/x/crypto/openpgp/read_test.go | 463 +++ .../golang.org/x/crypto/openpgp/s2k/s2k.go | 273 ++ .../x/crypto/openpgp/s2k/s2k_test.go | 137 + .../src/golang.org/x/crypto/openpgp/write.go | 374 +++ .../golang.org/x/crypto/openpgp/write_test.go | 234 ++ .../_workspace/src/gopkg.in/yaml.v2/LICENSE | 188 ++ .../src/gopkg.in/yaml.v2/LICENSE.libyaml | 31 + .../_workspace/src/gopkg.in/yaml.v2/README.md | 128 + .../_workspace/src/gopkg.in/yaml.v2/apic.go | 742 +++++ .../_workspace/src/gopkg.in/yaml.v2/decode.go | 683 +++++ .../src/gopkg.in/yaml.v2/decode_test.go | 966 ++++++ .../src/gopkg.in/yaml.v2/emitterc.go | 1685 ++++++++++ .../_workspace/src/gopkg.in/yaml.v2/encode.go | 306 ++ .../src/gopkg.in/yaml.v2/encode_test.go | 485 +++ .../src/gopkg.in/yaml.v2/parserc.go | 1096 +++++++ .../src/gopkg.in/yaml.v2/readerc.go | 391 +++ .../src/gopkg.in/yaml.v2/resolve.go | 203 ++ .../src/gopkg.in/yaml.v2/scannerc.go | 2710 +++++++++++++++++ .../_workspace/src/gopkg.in/yaml.v2/sorter.go | 104 + .../src/gopkg.in/yaml.v2/suite_test.go | 12 + .../src/gopkg.in/yaml.v2/writerc.go | 89 + .../_workspace/src/gopkg.in/yaml.v2/yaml.go | 344 +++ .../_workspace/src/gopkg.in/yaml.v2/yamlh.go | 716 +++++ .../src/gopkg.in/yaml.v2/yamlprivateh.go | 173 ++ assets/bindata.go | 384 +++ client/gulpfile.js | 15 +- commands/config.go | 48 + commands/name_pending.go | 14 +- config.default.toml | 1 + main.go | 25 + server/bindata.go | 361 --- server/serve_files.go | 6 +- storage/storage.go | 17 +- storage/user.go | 4 +- 234 files changed, 44636 insertions(+), 383 deletions(-) create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/.gitignore create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/.travis.yml create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/COMPATIBLE create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/COPYING create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/Makefile create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/README.md create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/COPYING create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/README.md create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/main.go create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/COPYING create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/README.md create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/main.go create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/COPYING create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/README.md create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/main.go create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/decode.go create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/decode_meta.go create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/decode_test.go create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/doc.go create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/encode.go create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/encode_test.go create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/encoding_types.go create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/encoding_types_1.1.go create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/lex.go create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/parse.go create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/session.vim create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/type_check.go create mode 100644 Godeps/_workspace/src/github.com/BurntSushi/toml/type_fields.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/.gitignore create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/LICENSE create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/README.md create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/acl.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/acl_test.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/agent.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/agent_test.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/api.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/api_test.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/catalog.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/catalog_test.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/event.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/event_test.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/health.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/health_test.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/kv.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/kv_test.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/session.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/session_test.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/status.go create mode 100644 Godeps/_workspace/src/github.com/armon/consul-api/status_test.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/add_child.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/add_child_test.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/client.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/client_test.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/cluster.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_delete.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_delete_test.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_swap.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_swap_test.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/debug.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/debug_test.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/delete.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/delete_test.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/error.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/get.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/get_test.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/member.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/member_test.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/options.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/requests.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/requests_test.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/response.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/set_curl_chan_test.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/set_update_create.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/set_update_create_test.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/version.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/watch.go create mode 100644 Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/watch_test.go create mode 100644 Godeps/_workspace/src/github.com/kr/pretty/.gitignore create mode 100644 Godeps/_workspace/src/github.com/kr/pretty/License create mode 100644 Godeps/_workspace/src/github.com/kr/pretty/Readme create mode 100644 Godeps/_workspace/src/github.com/kr/pretty/diff.go create mode 100644 Godeps/_workspace/src/github.com/kr/pretty/diff_test.go create mode 100644 Godeps/_workspace/src/github.com/kr/pretty/example_test.go create mode 100644 Godeps/_workspace/src/github.com/kr/pretty/formatter.go create mode 100644 Godeps/_workspace/src/github.com/kr/pretty/formatter_test.go create mode 100644 Godeps/_workspace/src/github.com/kr/pretty/pretty.go create mode 100644 Godeps/_workspace/src/github.com/kr/pretty/zero.go create mode 100644 Godeps/_workspace/src/github.com/kr/text/License create mode 100644 Godeps/_workspace/src/github.com/kr/text/Readme create mode 100644 Godeps/_workspace/src/github.com/kr/text/colwriter/Readme create mode 100644 Godeps/_workspace/src/github.com/kr/text/colwriter/column.go create mode 100644 Godeps/_workspace/src/github.com/kr/text/colwriter/column_test.go create mode 100644 Godeps/_workspace/src/github.com/kr/text/doc.go create mode 100644 Godeps/_workspace/src/github.com/kr/text/indent.go create mode 100644 Godeps/_workspace/src/github.com/kr/text/indent_test.go create mode 100644 Godeps/_workspace/src/github.com/kr/text/mc/Readme create mode 100644 Godeps/_workspace/src/github.com/kr/text/mc/mc.go create mode 100644 Godeps/_workspace/src/github.com/kr/text/wrap.go create mode 100644 Godeps/_workspace/src/github.com/kr/text/wrap_test.go create mode 100644 Godeps/_workspace/src/github.com/magiconair/properties/.gitignore create mode 100644 Godeps/_workspace/src/github.com/magiconair/properties/.travis.yml create mode 100644 Godeps/_workspace/src/github.com/magiconair/properties/LICENSE create mode 100644 Godeps/_workspace/src/github.com/magiconair/properties/README.md create mode 100644 Godeps/_workspace/src/github.com/magiconair/properties/benchmark_test.go create mode 100644 Godeps/_workspace/src/github.com/magiconair/properties/doc.go create mode 100644 Godeps/_workspace/src/github.com/magiconair/properties/example_test.go create mode 100644 Godeps/_workspace/src/github.com/magiconair/properties/lex.go create mode 100644 Godeps/_workspace/src/github.com/magiconair/properties/load.go create mode 100644 Godeps/_workspace/src/github.com/magiconair/properties/load_test.go create mode 100644 Godeps/_workspace/src/github.com/magiconair/properties/parser.go create mode 100644 Godeps/_workspace/src/github.com/magiconair/properties/properties.go create mode 100644 Godeps/_workspace/src/github.com/magiconair/properties/properties_test.go create mode 100644 Godeps/_workspace/src/github.com/magiconair/properties/rangecheck.go create mode 100644 Godeps/_workspace/src/github.com/mitchellh/mapstructure/.travis.yml create mode 100644 Godeps/_workspace/src/github.com/mitchellh/mapstructure/LICENSE create mode 100644 Godeps/_workspace/src/github.com/mitchellh/mapstructure/README.md create mode 100644 Godeps/_workspace/src/github.com/mitchellh/mapstructure/decode_hooks.go create mode 100644 Godeps/_workspace/src/github.com/mitchellh/mapstructure/decode_hooks_test.go create mode 100644 Godeps/_workspace/src/github.com/mitchellh/mapstructure/error.go create mode 100644 Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure.go create mode 100644 Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_benchmark_test.go create mode 100644 Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_bugs_test.go create mode 100644 Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_examples_test.go create mode 100644 Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_test.go create mode 100644 Godeps/_workspace/src/github.com/spf13/cast/.gitignore create mode 100644 Godeps/_workspace/src/github.com/spf13/cast/LICENSE create mode 100644 Godeps/_workspace/src/github.com/spf13/cast/README.md create mode 100644 Godeps/_workspace/src/github.com/spf13/cast/cast.go create mode 100644 Godeps/_workspace/src/github.com/spf13/cast/cast_test.go create mode 100644 Godeps/_workspace/src/github.com/spf13/cast/caste.go create mode 100644 Godeps/_workspace/src/github.com/spf13/jwalterweatherman/.gitignore create mode 100644 Godeps/_workspace/src/github.com/spf13/jwalterweatherman/LICENSE create mode 100644 Godeps/_workspace/src/github.com/spf13/jwalterweatherman/README.md create mode 100644 Godeps/_workspace/src/github.com/spf13/jwalterweatherman/jww_test.go create mode 100644 Godeps/_workspace/src/github.com/spf13/jwalterweatherman/thatswhyyoualwaysleaveanote.go create mode 100644 Godeps/_workspace/src/github.com/spf13/viper/.gitignore create mode 100644 Godeps/_workspace/src/github.com/spf13/viper/.travis.yml create mode 100644 Godeps/_workspace/src/github.com/spf13/viper/LICENSE create mode 100644 Godeps/_workspace/src/github.com/spf13/viper/README.md create mode 100644 Godeps/_workspace/src/github.com/spf13/viper/util.go create mode 100644 Godeps/_workspace/src/github.com/spf13/viper/viper.go create mode 100644 Godeps/_workspace/src/github.com/spf13/viper/viper_test.go create mode 100644 Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/backend.go create mode 100644 Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/consul/consul.go create mode 100644 Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/etcd/etcd.go create mode 100644 Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/mock/mock.go create mode 100644 Godeps/_workspace/src/github.com/xordataexchange/crypt/config/README.md create mode 100644 Godeps/_workspace/src/github.com/xordataexchange/crypt/config/config.go create mode 100644 Godeps/_workspace/src/github.com/xordataexchange/crypt/config/config_test.go create mode 100644 Godeps/_workspace/src/github.com/xordataexchange/crypt/encoding/secconf/keyring_test.go create mode 100644 Godeps/_workspace/src/github.com/xordataexchange/crypt/encoding/secconf/secconf.go create mode 100644 Godeps/_workspace/src/github.com/xordataexchange/crypt/encoding/secconf/secconf_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/cast5/cast5.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/cast5/cast5_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/armor/armor.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/armor/armor_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/armor/encode.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/canonical_text.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/canonical_text_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/clearsign/clearsign.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/elgamal/elgamal.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors/errors.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/keys.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/keys_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/compressed.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/compressed_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/config.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/encrypted_key.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/literal.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/ocfb.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/ocfb_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/one_pass_signature.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/opaque.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/opaque_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/packet.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/packet_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/private_key.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/private_key_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/public_key.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/public_key_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/public_key_v3.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/reader.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/signature.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/signature_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/signature_v3.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/signature_v3_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/userattribute.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/userattribute_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/userid.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/userid_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/read.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/read_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/s2k/s2k.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/s2k/s2k_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/write.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/openpgp/write_test.go create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/LICENSE create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/LICENSE.libyaml create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/README.md create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/apic.go create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/decode.go create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/decode_test.go create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/emitterc.go create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/encode.go create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/encode_test.go create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/parserc.go create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/readerc.go create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/resolve.go create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/scannerc.go create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/sorter.go create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/suite_test.go create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/writerc.go create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/yaml.go create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/yamlh.go create mode 100644 Godeps/_workspace/src/gopkg.in/yaml.v2/yamlprivateh.go create mode 100644 assets/bindata.go create mode 100644 commands/config.go create mode 100644 config.default.toml delete mode 100644 server/bindata.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index c7442566..319e87d1 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1,10 +1,19 @@ { "ImportPath": "github.com/khlieng/name_pending", - "GoVersion": "go1.4", + "GoVersion": "go1.4.2", "Packages": [ "./..." ], "Deps": [ + { + "ImportPath": "github.com/BurntSushi/toml", + "Comment": "v0.1.0-21-g056c9bc", + "Rev": "056c9bc7be7190eaa7715723883caffa5f8fa3e4" + }, + { + "ImportPath": "github.com/armon/consul-api", + "Rev": "dcfedd50ed5334f96adee43fc88518a4f095e15c" + }, { "ImportPath": "github.com/blevesearch/bleve", "Rev": "16f538d7b76dd85c935a3104c390307cae5cbf79" @@ -23,6 +32,11 @@ "Comment": "v1.0-43-gcf33c9e", "Rev": "cf33c9e0ca0a23509b8bb8edfc63e4776bb1a330" }, + { + "ImportPath": "github.com/coreos/go-etcd/etcd", + "Comment": "v2.0.0-7-g73a8ef7", + "Rev": "73a8ef737e8ea002281a28b4cb92a1de121ad4c6" + }, { "ImportPath": "github.com/cznic/b", "Rev": "c4adf3a58579a2d57cd3097f455dcdf75edcdfd8" @@ -43,18 +57,48 @@ "ImportPath": "github.com/julienschmidt/httprouter", "Rev": "b428fda53bb0a764fea9c76c9413512eda291dec" }, + { + "ImportPath": "github.com/kr/pretty", + "Comment": "go.weekly.2011-12-22-27-ge6ac2fc", + "Rev": "e6ac2fc51e89a3249e82157fa0bb7a18ef9dd5bb" + }, + { + "ImportPath": "github.com/kr/text", + "Rev": "e373e137fafd8abd480af49182dea0513914adb4" + }, + { + "ImportPath": "github.com/magiconair/properties", + "Comment": "v1.5.2", + "Rev": "d5929c67198951106f49f7ea425198d0f1a08f7f" + }, + { + "ImportPath": "github.com/mitchellh/mapstructure", + "Rev": "f7d28d5aeab42b9b95d2e6d6b956f73a290077fc" + }, { "ImportPath": "github.com/ryszard/goskiplist/skiplist", "Rev": "2dfbae5fcf46374f166f8969cb07e167f1be6273" }, + { + "ImportPath": "github.com/spf13/cast", + "Rev": "4d07383ffe94b5e5a6fa3af9211374a4507a0184" + }, { "ImportPath": "github.com/spf13/cobra", "Rev": "3ee9552eebbb5db27cb81abcae66c6f1430cad29" }, + { + "ImportPath": "github.com/spf13/jwalterweatherman", + "Rev": "3d60171a64319ef63c78bd45bd60e6eab1e75f8b" + }, { "ImportPath": "github.com/spf13/pflag", "Rev": "32bfad653e29e893e4ed3812fdc0294a05126c08" }, + { + "ImportPath": "github.com/spf13/viper", + "Rev": "d62d4bb4c68a773c3b5f4e72844913a2d5de0de0" + }, { "ImportPath": "github.com/steveyen/gtreap", "Rev": "72cd76f34c91f8d64a031af97b499e4a0b1a6e0c" @@ -72,6 +116,29 @@ "Comment": "v1.0.0-17-g4b22041", "Rev": "4b220417a489359f934045d0509d941a7a2a1038" }, + { + "ImportPath": "github.com/xordataexchange/crypt/backend", + "Comment": "v0.0.2-17-g749e360", + "Rev": "749e360c8f236773f28fc6d3ddfce4a470795227" + }, + { + "ImportPath": "github.com/xordataexchange/crypt/config", + "Comment": "v0.0.2-17-g749e360", + "Rev": "749e360c8f236773f28fc6d3ddfce4a470795227" + }, + { + "ImportPath": "github.com/xordataexchange/crypt/encoding/secconf", + "Comment": "v0.0.2-17-g749e360", + "Rev": "749e360c8f236773f28fc6d3ddfce4a470795227" + }, + { + "ImportPath": "golang.org/x/crypto/cast5", + "Rev": "644910e6da851dcd66a424c71d068d971cfacba5" + }, + { + "ImportPath": "golang.org/x/crypto/openpgp", + "Rev": "644910e6da851dcd66a424c71d068d971cfacba5" + }, { "ImportPath": "golang.org/x/text/transform", "Rev": "c92eb3cd6e70951a111680995e651ea4b2c35539" @@ -79,6 +146,10 @@ { "ImportPath": "golang.org/x/text/unicode/norm", "Rev": "c92eb3cd6e70951a111680995e651ea4b2c35539" + }, + { + "ImportPath": "gopkg.in/yaml.v2", + "Rev": "49c95bdc21843256fb6c4e0d370a05f24a0bf213" } ] } diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/.gitignore b/Godeps/_workspace/src/github.com/BurntSushi/toml/.gitignore new file mode 100644 index 00000000..0cd38003 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/.gitignore @@ -0,0 +1,5 @@ +TAGS +tags +.*.swp +tomlcheck/tomlcheck +toml.test diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/.travis.yml b/Godeps/_workspace/src/github.com/BurntSushi/toml/.travis.yml new file mode 100644 index 00000000..43caf6d0 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/.travis.yml @@ -0,0 +1,12 @@ +language: go +go: + - 1.1 + - 1.2 + - tip +install: + - go install ./... + - go get github.com/BurntSushi/toml-test +script: + - export PATH="$PATH:$HOME/gopath/bin" + - make test + diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/COMPATIBLE b/Godeps/_workspace/src/github.com/BurntSushi/toml/COMPATIBLE new file mode 100644 index 00000000..21e0938c --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/COMPATIBLE @@ -0,0 +1,3 @@ +Compatible with TOML version +[v0.2.0](https://github.com/mojombo/toml/blob/master/versions/toml-v0.2.0.md) + diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/COPYING b/Godeps/_workspace/src/github.com/BurntSushi/toml/COPYING new file mode 100644 index 00000000..5a8e3325 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/COPYING @@ -0,0 +1,14 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. + diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/Makefile b/Godeps/_workspace/src/github.com/BurntSushi/toml/Makefile new file mode 100644 index 00000000..3600848d --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/Makefile @@ -0,0 +1,19 @@ +install: + go install ./... + +test: install + go test -v + toml-test toml-test-decoder + toml-test -encoder toml-test-encoder + +fmt: + gofmt -w *.go */*.go + colcheck *.go */*.go + +tags: + find ./ -name '*.go' -print0 | xargs -0 gotags > TAGS + +push: + git push origin master + git push github master + diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/README.md b/Godeps/_workspace/src/github.com/BurntSushi/toml/README.md new file mode 100644 index 00000000..5a5df637 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/README.md @@ -0,0 +1,220 @@ +## TOML parser and encoder for Go with reflection + +TOML stands for Tom's Obvious, Minimal Language. This Go package provides a +reflection interface similar to Go's standard library `json` and `xml` +packages. This package also supports the `encoding.TextUnmarshaler` and +`encoding.TextMarshaler` interfaces so that you can define custom data +representations. (There is an example of this below.) + +Spec: https://github.com/mojombo/toml + +Compatible with TOML version +[v0.2.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.2.0.md) + +Documentation: http://godoc.org/github.com/BurntSushi/toml + +Installation: + +```bash +go get github.com/BurntSushi/toml +``` + +Try the toml validator: + +```bash +go get github.com/BurntSushi/toml/cmd/tomlv +tomlv some-toml-file.toml +``` + +[![Build status](https://api.travis-ci.org/BurntSushi/toml.png)](https://travis-ci.org/BurntSushi/toml) + + +### Testing + +This package passes all tests in +[toml-test](https://github.com/BurntSushi/toml-test) for both the decoder +and the encoder. + +### Examples + +This package works similarly to how the Go standard library handles `XML` +and `JSON`. Namely, data is loaded into Go values via reflection. + +For the simplest example, consider some TOML file as just a list of keys +and values: + +```toml +Age = 25 +Cats = [ "Cauchy", "Plato" ] +Pi = 3.14 +Perfection = [ 6, 28, 496, 8128 ] +DOB = 1987-07-05T05:45:00Z +``` + +Which could be defined in Go as: + +```go +type Config struct { + Age int + Cats []string + Pi float64 + Perfection []int + DOB time.Time // requires `import time` +} +``` + +And then decoded with: + +```go +var conf Config +if _, err := toml.Decode(tomlData, &conf); err != nil { + // handle error +} +``` + +You can also use struct tags if your struct field name doesn't map to a TOML +key value directly: + +```toml +some_key_NAME = "wat" +``` + +```go +type TOML struct { + ObscureKey string `toml:"some_key_NAME"` +} +``` + +### Using the `encoding.TextUnmarshaler` interface + +Here's an example that automatically parses duration strings into +`time.Duration` values: + +```toml +[[song]] +name = "Thunder Road" +duration = "4m49s" + +[[song]] +name = "Stairway to Heaven" +duration = "8m03s" +``` + +Which can be decoded with: + +```go +type song struct { + Name string + Duration duration +} +type songs struct { + Song []song +} +var favorites songs +if _, err := toml.Decode(blob, &favorites); err != nil { + log.Fatal(err) +} + +for _, s := range favorites.Song { + fmt.Printf("%s (%s)\n", s.Name, s.Duration) +} +``` + +And you'll also need a `duration` type that satisfies the +`encoding.TextUnmarshaler` interface: + +```go +type duration struct { + time.Duration +} + +func (d *duration) UnmarshalText(text []byte) error { + var err error + d.Duration, err = time.ParseDuration(string(text)) + return err +} +``` + +### More complex usage + +Here's an example of how to load the example from the official spec page: + +```toml +# This is a TOML document. Boom. + +title = "TOML Example" + +[owner] +name = "Tom Preston-Werner" +organization = "GitHub" +bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." +dob = 1979-05-27T07:32:00Z # First class dates? Why not? + +[database] +server = "192.168.1.1" +ports = [ 8001, 8001, 8002 ] +connection_max = 5000 +enabled = true + +[servers] + + # You can indent as you please. Tabs or spaces. TOML don't care. + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" + +[clients] +data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it + +# Line breaks are OK when inside arrays +hosts = [ + "alpha", + "omega" +] +``` + +And the corresponding Go types are: + +```go +type tomlConfig struct { + Title string + Owner ownerInfo + DB database `toml:"database"` + Servers map[string]server + Clients clients +} + +type ownerInfo struct { + Name string + Org string `toml:"organization"` + Bio string + DOB time.Time +} + +type database struct { + Server string + Ports []int + ConnMax int `toml:"connection_max"` + Enabled bool +} + +type server struct { + IP string + DC string +} + +type clients struct { + Data [][]interface{} + Hosts []string +} +``` + +Note that a case insensitive match will be tried if an exact match can't be +found. + +A working example of the above can be found in `_examples/example.{go,toml}`. + diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/COPYING b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/COPYING new file mode 100644 index 00000000..5a8e3325 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/COPYING @@ -0,0 +1,14 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. + diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/README.md b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/README.md new file mode 100644 index 00000000..24421eb7 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/README.md @@ -0,0 +1,14 @@ +# Implements the TOML test suite interface + +This is an implementation of the interface expected by +[toml-test](https://github.com/BurntSushi/toml-test) for my +[toml parser written in Go](https://github.com/BurntSushi/toml). +In particular, it maps TOML data on `stdin` to a JSON format on `stdout`. + + +Compatible with TOML version +[v0.2.0](https://github.com/mojombo/toml/blob/master/versions/toml-v0.2.0.md) + +Compatible with `toml-test` version +[v0.2.0](https://github.com/BurntSushi/toml-test/tree/v0.2.0) + diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/main.go b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/main.go new file mode 100644 index 00000000..045be453 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/main.go @@ -0,0 +1,90 @@ +// Command toml-test-decoder satisfies the toml-test interface for testing +// TOML decoders. Namely, it accepts TOML on stdin and outputs JSON on stdout. +package main + +import ( + "encoding/json" + "flag" + "fmt" + "log" + "os" + "path" + "time" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/BurntSushi/toml" +) + +func init() { + log.SetFlags(0) + + flag.Usage = usage + flag.Parse() +} + +func usage() { + log.Printf("Usage: %s < toml-file\n", path.Base(os.Args[0])) + flag.PrintDefaults() + + os.Exit(1) +} + +func main() { + if flag.NArg() != 0 { + flag.Usage() + } + + var tmp interface{} + if _, err := toml.DecodeReader(os.Stdin, &tmp); err != nil { + log.Fatalf("Error decoding TOML: %s", err) + } + + typedTmp := translate(tmp) + if err := json.NewEncoder(os.Stdout).Encode(typedTmp); err != nil { + log.Fatalf("Error encoding JSON: %s", err) + } +} + +func translate(tomlData interface{}) interface{} { + switch orig := tomlData.(type) { + case map[string]interface{}: + typed := make(map[string]interface{}, len(orig)) + for k, v := range orig { + typed[k] = translate(v) + } + return typed + case []map[string]interface{}: + typed := make([]map[string]interface{}, len(orig)) + for i, v := range orig { + typed[i] = translate(v).(map[string]interface{}) + } + return typed + case []interface{}: + typed := make([]interface{}, len(orig)) + for i, v := range orig { + typed[i] = translate(v) + } + + // We don't really need to tag arrays, but let's be future proof. + // (If TOML ever supports tuples, we'll need this.) + return tag("array", typed) + case time.Time: + return tag("datetime", orig.Format("2006-01-02T15:04:05Z")) + case bool: + return tag("bool", fmt.Sprintf("%v", orig)) + case int64: + return tag("integer", fmt.Sprintf("%d", orig)) + case float64: + return tag("float", fmt.Sprintf("%v", orig)) + case string: + return tag("string", orig) + } + + panic(fmt.Sprintf("Unknown type: %T", tomlData)) +} + +func tag(typeName string, data interface{}) map[string]interface{} { + return map[string]interface{}{ + "type": typeName, + "value": data, + } +} diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/COPYING b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/COPYING new file mode 100644 index 00000000..5a8e3325 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/COPYING @@ -0,0 +1,14 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. + diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/README.md b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/README.md new file mode 100644 index 00000000..45a603f2 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/README.md @@ -0,0 +1,14 @@ +# Implements the TOML test suite interface for TOML encoders + +This is an implementation of the interface expected by +[toml-test](https://github.com/BurntSushi/toml-test) for the +[TOML encoder](https://github.com/BurntSushi/toml). +In particular, it maps JSON data on `stdin` to a TOML format on `stdout`. + + +Compatible with TOML version +[v0.2.0](https://github.com/mojombo/toml/blob/master/versions/toml-v0.2.0.md) + +Compatible with `toml-test` version +[v0.2.0](https://github.com/BurntSushi/toml-test/tree/v0.2.0) + diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/main.go b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/main.go new file mode 100644 index 00000000..4e66fbd3 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/main.go @@ -0,0 +1,131 @@ +// Command toml-test-encoder satisfies the toml-test interface for testing +// TOML encoders. Namely, it accepts JSON on stdin and outputs TOML on stdout. +package main + +import ( + "encoding/json" + "flag" + "log" + "os" + "path" + "strconv" + "time" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/BurntSushi/toml" +) + +func init() { + log.SetFlags(0) + + flag.Usage = usage + flag.Parse() +} + +func usage() { + log.Printf("Usage: %s < json-file\n", path.Base(os.Args[0])) + flag.PrintDefaults() + + os.Exit(1) +} + +func main() { + if flag.NArg() != 0 { + flag.Usage() + } + + var tmp interface{} + if err := json.NewDecoder(os.Stdin).Decode(&tmp); err != nil { + log.Fatalf("Error decoding JSON: %s", err) + } + + tomlData := translate(tmp) + if err := toml.NewEncoder(os.Stdout).Encode(tomlData); err != nil { + log.Fatalf("Error encoding TOML: %s", err) + } +} + +func translate(typedJson interface{}) interface{} { + switch v := typedJson.(type) { + case map[string]interface{}: + if len(v) == 2 && in("type", v) && in("value", v) { + return untag(v) + } + m := make(map[string]interface{}, len(v)) + for k, v2 := range v { + m[k] = translate(v2) + } + return m + case []interface{}: + tabArray := make([]map[string]interface{}, len(v)) + for i := range v { + if m, ok := translate(v[i]).(map[string]interface{}); ok { + tabArray[i] = m + } else { + log.Fatalf("JSON arrays may only contain objects. This " + + "corresponds to only tables being allowed in " + + "TOML table arrays.") + } + } + return tabArray + } + log.Fatalf("Unrecognized JSON format '%T'.", typedJson) + panic("unreachable") +} + +func untag(typed map[string]interface{}) interface{} { + t := typed["type"].(string) + v := typed["value"] + switch t { + case "string": + return v.(string) + case "integer": + v := v.(string) + n, err := strconv.Atoi(v) + if err != nil { + log.Fatalf("Could not parse '%s' as integer: %s", v, err) + } + return n + case "float": + v := v.(string) + f, err := strconv.ParseFloat(v, 64) + if err != nil { + log.Fatalf("Could not parse '%s' as float64: %s", v, err) + } + return f + case "datetime": + v := v.(string) + t, err := time.Parse("2006-01-02T15:04:05Z", v) + if err != nil { + log.Fatalf("Could not parse '%s' as a datetime: %s", v, err) + } + return t + case "bool": + v := v.(string) + switch v { + case "true": + return true + case "false": + return false + } + log.Fatalf("Could not parse '%s' as a boolean.", v) + case "array": + v := v.([]interface{}) + array := make([]interface{}, len(v)) + for i := range v { + if m, ok := v[i].(map[string]interface{}); ok { + array[i] = untag(m) + } else { + log.Fatalf("Arrays may only contain other arrays or "+ + "primitive values, but found a '%T'.", m) + } + } + return array + } + log.Fatalf("Unrecognized tag type '%s'.", t) + panic("unreachable") +} + +func in(key string, m map[string]interface{}) bool { + _, ok := m[key] + return ok +} diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/COPYING b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/COPYING new file mode 100644 index 00000000..5a8e3325 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/COPYING @@ -0,0 +1,14 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. + diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/README.md b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/README.md new file mode 100644 index 00000000..5df0dc32 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/README.md @@ -0,0 +1,22 @@ +# TOML Validator + +If Go is installed, it's simple to try it out: + +```bash +go get github.com/BurntSushi/toml/cmd/tomlv +tomlv some-toml-file.toml +``` + +You can see the types of every key in a TOML file with: + +```bash +tomlv -types some-toml-file.toml +``` + +At the moment, only one error message is reported at a time. Error messages +include line numbers. No output means that the files given are valid TOML, or +there is a bug in `tomlv`. + +Compatible with TOML version +[v0.1.0](https://github.com/mojombo/toml/blob/master/versions/toml-v0.1.0.md) + diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/main.go b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/main.go new file mode 100644 index 00000000..be1d9006 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/main.go @@ -0,0 +1,61 @@ +// Command tomlv validates TOML documents and prints each key's type. +package main + +import ( + "flag" + "fmt" + "log" + "os" + "path" + "strings" + "text/tabwriter" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/BurntSushi/toml" +) + +var ( + flagTypes = false +) + +func init() { + log.SetFlags(0) + + flag.BoolVar(&flagTypes, "types", flagTypes, + "When set, the types of every defined key will be shown.") + + flag.Usage = usage + flag.Parse() +} + +func usage() { + log.Printf("Usage: %s toml-file [ toml-file ... ]\n", + path.Base(os.Args[0])) + flag.PrintDefaults() + + os.Exit(1) +} + +func main() { + if flag.NArg() < 1 { + flag.Usage() + } + for _, f := range flag.Args() { + var tmp interface{} + md, err := toml.DecodeFile(f, &tmp) + if err != nil { + log.Fatalf("Error in '%s': %s", f, err) + } + if flagTypes { + printTypes(md) + } + } +} + +func printTypes(md toml.MetaData) { + tabw := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) + for _, key := range md.Keys() { + fmt.Fprintf(tabw, "%s%s\t%s\n", + strings.Repeat(" ", len(key)-1), key, md.Type(key...)) + } + tabw.Flush() +} diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/decode.go b/Godeps/_workspace/src/github.com/BurntSushi/toml/decode.go new file mode 100644 index 00000000..6c7d398b --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/decode.go @@ -0,0 +1,492 @@ +package toml + +import ( + "fmt" + "io" + "io/ioutil" + "math" + "reflect" + "strings" + "time" +) + +var e = fmt.Errorf + +// Unmarshaler is the interface implemented by objects that can unmarshal a +// TOML description of themselves. +type Unmarshaler interface { + UnmarshalTOML(interface{}) error +} + +// Unmarshal decodes the contents of `p` in TOML format into a pointer `v`. +func Unmarshal(p []byte, v interface{}) error { + _, err := Decode(string(p), v) + return err +} + +// Primitive is a TOML value that hasn't been decoded into a Go value. +// When using the various `Decode*` functions, the type `Primitive` may +// be given to any value, and its decoding will be delayed. +// +// A `Primitive` value can be decoded using the `PrimitiveDecode` function. +// +// The underlying representation of a `Primitive` value is subject to change. +// Do not rely on it. +// +// N.B. Primitive values are still parsed, so using them will only avoid +// the overhead of reflection. They can be useful when you don't know the +// exact type of TOML data until run time. +type Primitive struct { + undecoded interface{} + context Key +} + +// DEPRECATED! +// +// Use MetaData.PrimitiveDecode instead. +func PrimitiveDecode(primValue Primitive, v interface{}) error { + md := MetaData{decoded: make(map[string]bool)} + return md.unify(primValue.undecoded, rvalue(v)) +} + +// PrimitiveDecode is just like the other `Decode*` functions, except it +// decodes a TOML value that has already been parsed. Valid primitive values +// can *only* be obtained from values filled by the decoder functions, +// including this method. (i.e., `v` may contain more `Primitive` +// values.) +// +// Meta data for primitive values is included in the meta data returned by +// the `Decode*` functions with one exception: keys returned by the Undecoded +// method will only reflect keys that were decoded. Namely, any keys hidden +// behind a Primitive will be considered undecoded. Executing this method will +// update the undecoded keys in the meta data. (See the example.) +func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error { + md.context = primValue.context + defer func() { md.context = nil }() + return md.unify(primValue.undecoded, rvalue(v)) +} + +// Decode will decode the contents of `data` in TOML format into a pointer +// `v`. +// +// TOML hashes correspond to Go structs or maps. (Dealer's choice. They can be +// used interchangeably.) +// +// TOML arrays of tables correspond to either a slice of structs or a slice +// of maps. +// +// TOML datetimes correspond to Go `time.Time` values. +// +// All other TOML types (float, string, int, bool and array) correspond +// to the obvious Go types. +// +// An exception to the above rules is if a type implements the +// encoding.TextUnmarshaler interface. In this case, any primitive TOML value +// (floats, strings, integers, booleans and datetimes) will be converted to +// a byte string and given to the value's UnmarshalText method. See the +// Unmarshaler example for a demonstration with time duration strings. +// +// Key mapping +// +// TOML keys can map to either keys in a Go map or field names in a Go +// struct. The special `toml` struct tag may be used to map TOML keys to +// struct fields that don't match the key name exactly. (See the example.) +// A case insensitive match to struct names will be tried if an exact match +// can't be found. +// +// The mapping between TOML values and Go values is loose. That is, there +// may exist TOML values that cannot be placed into your representation, and +// there may be parts of your representation that do not correspond to +// TOML values. This loose mapping can be made stricter by using the IsDefined +// and/or Undecoded methods on the MetaData returned. +// +// This decoder will not handle cyclic types. If a cyclic type is passed, +// `Decode` will not terminate. +func Decode(data string, v interface{}) (MetaData, error) { + p, err := parse(data) + if err != nil { + return MetaData{}, err + } + md := MetaData{ + p.mapping, p.types, p.ordered, + make(map[string]bool, len(p.ordered)), nil, + } + return md, md.unify(p.mapping, rvalue(v)) +} + +// DecodeFile is just like Decode, except it will automatically read the +// contents of the file at `fpath` and decode it for you. +func DecodeFile(fpath string, v interface{}) (MetaData, error) { + bs, err := ioutil.ReadFile(fpath) + if err != nil { + return MetaData{}, err + } + return Decode(string(bs), v) +} + +// DecodeReader is just like Decode, except it will consume all bytes +// from the reader and decode it for you. +func DecodeReader(r io.Reader, v interface{}) (MetaData, error) { + bs, err := ioutil.ReadAll(r) + if err != nil { + return MetaData{}, err + } + return Decode(string(bs), v) +} + +// unify performs a sort of type unification based on the structure of `rv`, +// which is the client representation. +// +// Any type mismatch produces an error. Finding a type that we don't know +// how to handle produces an unsupported type error. +func (md *MetaData) unify(data interface{}, rv reflect.Value) error { + + // Special case. Look for a `Primitive` value. + if rv.Type() == reflect.TypeOf((*Primitive)(nil)).Elem() { + // Save the undecoded data and the key context into the primitive + // value. + context := make(Key, len(md.context)) + copy(context, md.context) + rv.Set(reflect.ValueOf(Primitive{ + undecoded: data, + context: context, + })) + return nil + } + + // Special case. Unmarshaler Interface support. + if rv.CanAddr() { + if v, ok := rv.Addr().Interface().(Unmarshaler); ok { + return v.UnmarshalTOML(data) + } + } + + // Special case. Handle time.Time values specifically. + // TODO: Remove this code when we decide to drop support for Go 1.1. + // This isn't necessary in Go 1.2 because time.Time satisfies the encoding + // interfaces. + if rv.Type().AssignableTo(rvalue(time.Time{}).Type()) { + return md.unifyDatetime(data, rv) + } + + // Special case. Look for a value satisfying the TextUnmarshaler interface. + if v, ok := rv.Interface().(TextUnmarshaler); ok { + return md.unifyText(data, v) + } + // BUG(burntsushi) + // The behavior here is incorrect whenever a Go type satisfies the + // encoding.TextUnmarshaler interface but also corresponds to a TOML + // hash or array. In particular, the unmarshaler should only be applied + // to primitive TOML values. But at this point, it will be applied to + // all kinds of values and produce an incorrect error whenever those values + // are hashes or arrays (including arrays of tables). + + k := rv.Kind() + + // laziness + if k >= reflect.Int && k <= reflect.Uint64 { + return md.unifyInt(data, rv) + } + switch k { + case reflect.Ptr: + elem := reflect.New(rv.Type().Elem()) + err := md.unify(data, reflect.Indirect(elem)) + if err != nil { + return err + } + rv.Set(elem) + return nil + case reflect.Struct: + return md.unifyStruct(data, rv) + case reflect.Map: + return md.unifyMap(data, rv) + case reflect.Array: + return md.unifyArray(data, rv) + case reflect.Slice: + return md.unifySlice(data, rv) + case reflect.String: + return md.unifyString(data, rv) + case reflect.Bool: + return md.unifyBool(data, rv) + case reflect.Interface: + // we only support empty interfaces. + if rv.NumMethod() > 0 { + return e("Unsupported type '%s'.", rv.Kind()) + } + return md.unifyAnything(data, rv) + case reflect.Float32: + fallthrough + case reflect.Float64: + return md.unifyFloat64(data, rv) + } + return e("Unsupported type '%s'.", rv.Kind()) +} + +func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error { + tmap, ok := mapping.(map[string]interface{}) + if !ok { + return mismatch(rv, "map", mapping) + } + + for key, datum := range tmap { + var f *field + fields := cachedTypeFields(rv.Type()) + for i := range fields { + ff := &fields[i] + if ff.name == key { + f = ff + break + } + if f == nil && strings.EqualFold(ff.name, key) { + f = ff + } + } + if f != nil { + subv := rv + for _, i := range f.index { + subv = indirect(subv.Field(i)) + } + if isUnifiable(subv) { + md.decoded[md.context.add(key).String()] = true + md.context = append(md.context, key) + if err := md.unify(datum, subv); err != nil { + return e("Type mismatch for '%s.%s': %s", + rv.Type().String(), f.name, err) + } + md.context = md.context[0 : len(md.context)-1] + } else if f.name != "" { + // Bad user! No soup for you! + return e("Field '%s.%s' is unexported, and therefore cannot "+ + "be loaded with reflection.", rv.Type().String(), f.name) + } + } + } + return nil +} + +func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error { + tmap, ok := mapping.(map[string]interface{}) + if !ok { + return badtype("map", mapping) + } + if rv.IsNil() { + rv.Set(reflect.MakeMap(rv.Type())) + } + for k, v := range tmap { + md.decoded[md.context.add(k).String()] = true + md.context = append(md.context, k) + + rvkey := indirect(reflect.New(rv.Type().Key())) + rvval := reflect.Indirect(reflect.New(rv.Type().Elem())) + if err := md.unify(v, rvval); err != nil { + return err + } + md.context = md.context[0 : len(md.context)-1] + + rvkey.SetString(k) + rv.SetMapIndex(rvkey, rvval) + } + return nil +} + +func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error { + datav := reflect.ValueOf(data) + if datav.Kind() != reflect.Slice { + return badtype("slice", data) + } + sliceLen := datav.Len() + if sliceLen != rv.Len() { + return e("expected array length %d; got TOML array of length %d", + rv.Len(), sliceLen) + } + return md.unifySliceArray(datav, rv) +} + +func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error { + datav := reflect.ValueOf(data) + if datav.Kind() != reflect.Slice { + return badtype("slice", data) + } + sliceLen := datav.Len() + if rv.IsNil() { + rv.Set(reflect.MakeSlice(rv.Type(), sliceLen, sliceLen)) + } + return md.unifySliceArray(datav, rv) +} + +func (md *MetaData) unifySliceArray(data, rv reflect.Value) error { + sliceLen := data.Len() + for i := 0; i < sliceLen; i++ { + v := data.Index(i).Interface() + sliceval := indirect(rv.Index(i)) + if err := md.unify(v, sliceval); err != nil { + return err + } + } + return nil +} + +func (md *MetaData) unifyDatetime(data interface{}, rv reflect.Value) error { + if _, ok := data.(time.Time); ok { + rv.Set(reflect.ValueOf(data)) + return nil + } + return badtype("time.Time", data) +} + +func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error { + if s, ok := data.(string); ok { + rv.SetString(s) + return nil + } + return badtype("string", data) +} + +func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error { + if num, ok := data.(float64); ok { + switch rv.Kind() { + case reflect.Float32: + fallthrough + case reflect.Float64: + rv.SetFloat(num) + default: + panic("bug") + } + return nil + } + return badtype("float", data) +} + +func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error { + if num, ok := data.(int64); ok { + if rv.Kind() >= reflect.Int && rv.Kind() <= reflect.Int64 { + switch rv.Kind() { + case reflect.Int, reflect.Int64: + // No bounds checking necessary. + case reflect.Int8: + if num < math.MinInt8 || num > math.MaxInt8 { + return e("Value '%d' is out of range for int8.", num) + } + case reflect.Int16: + if num < math.MinInt16 || num > math.MaxInt16 { + return e("Value '%d' is out of range for int16.", num) + } + case reflect.Int32: + if num < math.MinInt32 || num > math.MaxInt32 { + return e("Value '%d' is out of range for int32.", num) + } + } + rv.SetInt(num) + } else if rv.Kind() >= reflect.Uint && rv.Kind() <= reflect.Uint64 { + unum := uint64(num) + switch rv.Kind() { + case reflect.Uint, reflect.Uint64: + // No bounds checking necessary. + case reflect.Uint8: + if num < 0 || unum > math.MaxUint8 { + return e("Value '%d' is out of range for uint8.", num) + } + case reflect.Uint16: + if num < 0 || unum > math.MaxUint16 { + return e("Value '%d' is out of range for uint16.", num) + } + case reflect.Uint32: + if num < 0 || unum > math.MaxUint32 { + return e("Value '%d' is out of range for uint32.", num) + } + } + rv.SetUint(unum) + } else { + panic("unreachable") + } + return nil + } + return badtype("integer", data) +} + +func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error { + if b, ok := data.(bool); ok { + rv.SetBool(b) + return nil + } + return badtype("boolean", data) +} + +func (md *MetaData) unifyAnything(data interface{}, rv reflect.Value) error { + rv.Set(reflect.ValueOf(data)) + return nil +} + +func (md *MetaData) unifyText(data interface{}, v TextUnmarshaler) error { + var s string + switch sdata := data.(type) { + case TextMarshaler: + text, err := sdata.MarshalText() + if err != nil { + return err + } + s = string(text) + case fmt.Stringer: + s = sdata.String() + case string: + s = sdata + case bool: + s = fmt.Sprintf("%v", sdata) + case int64: + s = fmt.Sprintf("%d", sdata) + case float64: + s = fmt.Sprintf("%f", sdata) + default: + return badtype("primitive (string-like)", data) + } + if err := v.UnmarshalText([]byte(s)); err != nil { + return err + } + return nil +} + +// rvalue returns a reflect.Value of `v`. All pointers are resolved. +func rvalue(v interface{}) reflect.Value { + return indirect(reflect.ValueOf(v)) +} + +// indirect returns the value pointed to by a pointer. +// Pointers are followed until the value is not a pointer. +// New values are allocated for each nil pointer. +// +// An exception to this rule is if the value satisfies an interface of +// interest to us (like encoding.TextUnmarshaler). +func indirect(v reflect.Value) reflect.Value { + if v.Kind() != reflect.Ptr { + if v.CanAddr() { + pv := v.Addr() + if _, ok := pv.Interface().(TextUnmarshaler); ok { + return pv + } + } + return v + } + if v.IsNil() { + v.Set(reflect.New(v.Type().Elem())) + } + return indirect(reflect.Indirect(v)) +} + +func isUnifiable(rv reflect.Value) bool { + if rv.CanSet() { + return true + } + if _, ok := rv.Interface().(TextUnmarshaler); ok { + return true + } + return false +} + +func badtype(expected string, data interface{}) error { + return e("Expected %s but found '%T'.", expected, data) +} + +func mismatch(user reflect.Value, expected string, data interface{}) error { + return e("Type mismatch for %s. Expected %s but found '%T'.", + user.Type().String(), expected, data) +} diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/decode_meta.go b/Godeps/_workspace/src/github.com/BurntSushi/toml/decode_meta.go new file mode 100644 index 00000000..ef6f545f --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/decode_meta.go @@ -0,0 +1,122 @@ +package toml + +import "strings" + +// MetaData allows access to meta information about TOML data that may not +// be inferrable via reflection. In particular, whether a key has been defined +// and the TOML type of a key. +type MetaData struct { + mapping map[string]interface{} + types map[string]tomlType + keys []Key + decoded map[string]bool + context Key // Used only during decoding. +} + +// IsDefined returns true if the key given exists in the TOML data. The key +// should be specified hierarchially. e.g., +// +// // access the TOML key 'a.b.c' +// IsDefined("a", "b", "c") +// +// IsDefined will return false if an empty key given. Keys are case sensitive. +func (md *MetaData) IsDefined(key ...string) bool { + if len(key) == 0 { + return false + } + + var hash map[string]interface{} + var ok bool + var hashOrVal interface{} = md.mapping + for _, k := range key { + if hash, ok = hashOrVal.(map[string]interface{}); !ok { + return false + } + if hashOrVal, ok = hash[k]; !ok { + return false + } + } + return true +} + +// Type returns a string representation of the type of the key specified. +// +// Type will return the empty string if given an empty key or a key that +// does not exist. Keys are case sensitive. +func (md *MetaData) Type(key ...string) string { + fullkey := strings.Join(key, ".") + if typ, ok := md.types[fullkey]; ok { + return typ.typeString() + } + return "" +} + +// Key is the type of any TOML key, including key groups. Use (MetaData).Keys +// to get values of this type. +type Key []string + +func (k Key) String() string { + return strings.Join(k, ".") +} + +func (k Key) maybeQuotedAll() string { + var ss []string + for i := range k { + ss = append(ss, k.maybeQuoted(i)) + } + return strings.Join(ss, ".") +} + +func (k Key) maybeQuoted(i int) string { + quote := false + for _, c := range k[i] { + if !isBareKeyChar(c) { + quote = true + break + } + } + if quote { + return "\"" + strings.Replace(k[i], "\"", "\\\"", -1) + "\"" + } else { + return k[i] + } +} + +func (k Key) add(piece string) Key { + newKey := make(Key, len(k)+1) + copy(newKey, k) + newKey[len(k)] = piece + return newKey +} + +// Keys returns a slice of every key in the TOML data, including key groups. +// Each key is itself a slice, where the first element is the top of the +// hierarchy and the last is the most specific. +// +// The list will have the same order as the keys appeared in the TOML data. +// +// All keys returned are non-empty. +func (md *MetaData) Keys() []Key { + return md.keys +} + +// Undecoded returns all keys that have not been decoded in the order in which +// they appear in the original TOML document. +// +// This includes keys that haven't been decoded because of a Primitive value. +// Once the Primitive value is decoded, the keys will be considered decoded. +// +// Also note that decoding into an empty interface will result in no decoding, +// and so no keys will be considered decoded. +// +// In this sense, the Undecoded keys correspond to keys in the TOML document +// that do not have a concrete type in your representation. +func (md *MetaData) Undecoded() []Key { + undecoded := make([]Key, 0, len(md.keys)) + for _, key := range md.keys { + if !md.decoded[key.String()] { + undecoded = append(undecoded, key) + } + } + return undecoded +} diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/decode_test.go b/Godeps/_workspace/src/github.com/BurntSushi/toml/decode_test.go new file mode 100644 index 00000000..3805931f --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/decode_test.go @@ -0,0 +1,950 @@ +package toml + +import ( + "fmt" + "log" + "reflect" + "testing" + "time" +) + +func init() { + log.SetFlags(0) +} + +func TestDecodeSimple(t *testing.T) { + var testSimple = ` +age = 250 +andrew = "gallant" +kait = "brady" +now = 1987-07-05T05:45:00Z +yesOrNo = true +pi = 3.14 +colors = [ + ["red", "green", "blue"], + ["cyan", "magenta", "yellow", "black"], +] + +[My.Cats] +plato = "cat 1" +cauchy = "cat 2" +` + + type cats struct { + Plato string + Cauchy string + } + type simple struct { + Age int + Colors [][]string + Pi float64 + YesOrNo bool + Now time.Time + Andrew string + Kait string + My map[string]cats + } + + var val simple + _, err := Decode(testSimple, &val) + if err != nil { + t.Fatal(err) + } + + now, err := time.Parse("2006-01-02T15:04:05", "1987-07-05T05:45:00") + if err != nil { + panic(err) + } + var answer = simple{ + Age: 250, + Andrew: "gallant", + Kait: "brady", + Now: now, + YesOrNo: true, + Pi: 3.14, + Colors: [][]string{ + {"red", "green", "blue"}, + {"cyan", "magenta", "yellow", "black"}, + }, + My: map[string]cats{ + "Cats": cats{Plato: "cat 1", Cauchy: "cat 2"}, + }, + } + if !reflect.DeepEqual(val, answer) { + t.Fatalf("Expected\n-----\n%#v\n-----\nbut got\n-----\n%#v\n", + answer, val) + } +} + +func TestDecodeEmbedded(t *testing.T) { + type Dog struct{ Name string } + type Age int + + tests := map[string]struct { + input string + decodeInto interface{} + wantDecoded interface{} + }{ + "embedded struct": { + input: `Name = "milton"`, + decodeInto: &struct{ Dog }{}, + wantDecoded: &struct{ Dog }{Dog{"milton"}}, + }, + "embedded non-nil pointer to struct": { + input: `Name = "milton"`, + decodeInto: &struct{ *Dog }{}, + wantDecoded: &struct{ *Dog }{&Dog{"milton"}}, + }, + "embedded nil pointer to struct": { + input: ``, + decodeInto: &struct{ *Dog }{}, + wantDecoded: &struct{ *Dog }{nil}, + }, + "embedded int": { + input: `Age = -5`, + decodeInto: &struct{ Age }{}, + wantDecoded: &struct{ Age }{-5}, + }, + } + + for label, test := range tests { + _, err := Decode(test.input, test.decodeInto) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(test.wantDecoded, test.decodeInto) { + t.Errorf("%s: want decoded == %+v, got %+v", + label, test.wantDecoded, test.decodeInto) + } + } +} + +func TestTableArrays(t *testing.T) { + var tomlTableArrays = ` +[[albums]] +name = "Born to Run" + + [[albums.songs]] + name = "Jungleland" + + [[albums.songs]] + name = "Meeting Across the River" + +[[albums]] +name = "Born in the USA" + + [[albums.songs]] + name = "Glory Days" + + [[albums.songs]] + name = "Dancing in the Dark" +` + + type Song struct { + Name string + } + + type Album struct { + Name string + Songs []Song + } + + type Music struct { + Albums []Album + } + + expected := Music{[]Album{ + {"Born to Run", []Song{{"Jungleland"}, {"Meeting Across the River"}}}, + {"Born in the USA", []Song{{"Glory Days"}, {"Dancing in the Dark"}}}, + }} + var got Music + if _, err := Decode(tomlTableArrays, &got); err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(expected, got) { + t.Fatalf("\n%#v\n!=\n%#v\n", expected, got) + } +} + +// Case insensitive matching tests. +// A bit more comprehensive than needed given the current implementation, +// but implementations change. +// Probably still missing demonstrations of some ugly corner cases regarding +// case insensitive matching and multiple fields. +func TestCase(t *testing.T) { + var caseToml = ` +tOpString = "string" +tOpInt = 1 +tOpFloat = 1.1 +tOpBool = true +tOpdate = 2006-01-02T15:04:05Z +tOparray = [ "array" ] +Match = "i should be in Match only" +MatcH = "i should be in MatcH only" +once = "just once" +[nEst.eD] +nEstedString = "another string" +` + + type InsensitiveEd struct { + NestedString string + } + + type InsensitiveNest struct { + Ed InsensitiveEd + } + + type Insensitive struct { + TopString string + TopInt int + TopFloat float64 + TopBool bool + TopDate time.Time + TopArray []string + Match string + MatcH string + Once string + OncE string + Nest InsensitiveNest + } + + tme, err := time.Parse(time.RFC3339, time.RFC3339[:len(time.RFC3339)-5]) + if err != nil { + panic(err) + } + expected := Insensitive{ + TopString: "string", + TopInt: 1, + TopFloat: 1.1, + TopBool: true, + TopDate: tme, + TopArray: []string{"array"}, + MatcH: "i should be in MatcH only", + Match: "i should be in Match only", + Once: "just once", + OncE: "", + Nest: InsensitiveNest{ + Ed: InsensitiveEd{NestedString: "another string"}, + }, + } + var got Insensitive + if _, err := Decode(caseToml, &got); err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(expected, got) { + t.Fatalf("\n%#v\n!=\n%#v\n", expected, got) + } +} + +func TestPointers(t *testing.T) { + type Object struct { + Type string + Description string + } + + type Dict struct { + NamedObject map[string]*Object + BaseObject *Object + Strptr *string + Strptrs []*string + } + s1, s2, s3 := "blah", "abc", "def" + expected := &Dict{ + Strptr: &s1, + Strptrs: []*string{&s2, &s3}, + NamedObject: map[string]*Object{ + "foo": {"FOO", "fooooo!!!"}, + "bar": {"BAR", "ba-ba-ba-ba-barrrr!!!"}, + }, + BaseObject: &Object{"BASE", "da base"}, + } + + ex1 := ` +Strptr = "blah" +Strptrs = ["abc", "def"] + +[NamedObject.foo] +Type = "FOO" +Description = "fooooo!!!" + +[NamedObject.bar] +Type = "BAR" +Description = "ba-ba-ba-ba-barrrr!!!" + +[BaseObject] +Type = "BASE" +Description = "da base" +` + dict := new(Dict) + _, err := Decode(ex1, dict) + if err != nil { + t.Errorf("Decode error: %v", err) + } + if !reflect.DeepEqual(expected, dict) { + t.Fatalf("\n%#v\n!=\n%#v\n", expected, dict) + } +} + +type sphere struct { + Center [3]float64 + Radius float64 +} + +func TestDecodeSimpleArray(t *testing.T) { + var s1 sphere + if _, err := Decode(`center = [0.0, 1.5, 0.0]`, &s1); err != nil { + t.Fatal(err) + } +} + +func TestDecodeArrayWrongSize(t *testing.T) { + var s1 sphere + if _, err := Decode(`center = [0.1, 2.3]`, &s1); err == nil { + t.Fatal("Expected array type mismatch error") + } +} + +func TestDecodeLargeIntoSmallInt(t *testing.T) { + type table struct { + Value int8 + } + var tab table + if _, err := Decode(`value = 500`, &tab); err == nil { + t.Fatal("Expected integer out-of-bounds error.") + } +} + +func TestDecodeSizedInts(t *testing.T) { + type table struct { + U8 uint8 + U16 uint16 + U32 uint32 + U64 uint64 + U uint + I8 int8 + I16 int16 + I32 int32 + I64 int64 + I int + } + answer := table{1, 1, 1, 1, 1, -1, -1, -1, -1, -1} + toml := ` + u8 = 1 + u16 = 1 + u32 = 1 + u64 = 1 + u = 1 + i8 = -1 + i16 = -1 + i32 = -1 + i64 = -1 + i = -1 + ` + var tab table + if _, err := Decode(toml, &tab); err != nil { + t.Fatal(err.Error()) + } + if answer != tab { + t.Fatalf("Expected %#v but got %#v", answer, tab) + } +} + +func TestUnmarshaler(t *testing.T) { + + var tomlBlob = ` +[dishes.hamboogie] +name = "Hamboogie with fries" +price = 10.99 + +[[dishes.hamboogie.ingredients]] +name = "Bread Bun" + +[[dishes.hamboogie.ingredients]] +name = "Lettuce" + +[[dishes.hamboogie.ingredients]] +name = "Real Beef Patty" + +[[dishes.hamboogie.ingredients]] +name = "Tomato" + +[dishes.eggsalad] +name = "Egg Salad with rice" +price = 3.99 + +[[dishes.eggsalad.ingredients]] +name = "Egg" + +[[dishes.eggsalad.ingredients]] +name = "Mayo" + +[[dishes.eggsalad.ingredients]] +name = "Rice" +` + m := &menu{} + if _, err := Decode(tomlBlob, m); err != nil { + log.Fatal(err) + } + + if len(m.Dishes) != 2 { + t.Log("two dishes should be loaded with UnmarshalTOML()") + t.Errorf("expected %d but got %d", 2, len(m.Dishes)) + } + + eggSalad := m.Dishes["eggsalad"] + if _, ok := interface{}(eggSalad).(dish); !ok { + t.Errorf("expected a dish") + } + + if eggSalad.Name != "Egg Salad with rice" { + t.Errorf("expected the dish to be named 'Egg Salad with rice'") + } + + if len(eggSalad.Ingredients) != 3 { + t.Log("dish should be loaded with UnmarshalTOML()") + t.Errorf("expected %d but got %d", 3, len(eggSalad.Ingredients)) + } + + found := false + for _, i := range eggSalad.Ingredients { + if i.Name == "Rice" { + found = true + break + } + } + if !found { + t.Error("Rice was not loaded in UnmarshalTOML()") + } + + // test on a value - must be passed as * + o := menu{} + if _, err := Decode(tomlBlob, &o); err != nil { + log.Fatal(err) + } + +} + +type menu struct { + Dishes map[string]dish +} + +func (m *menu) UnmarshalTOML(p interface{}) error { + m.Dishes = make(map[string]dish) + data, _ := p.(map[string]interface{}) + dishes := data["dishes"].(map[string]interface{}) + for n, v := range dishes { + if d, ok := v.(map[string]interface{}); ok { + nd := dish{} + nd.UnmarshalTOML(d) + m.Dishes[n] = nd + } else { + return fmt.Errorf("not a dish") + } + } + return nil +} + +type dish struct { + Name string + Price float32 + Ingredients []ingredient +} + +func (d *dish) UnmarshalTOML(p interface{}) error { + data, _ := p.(map[string]interface{}) + d.Name, _ = data["name"].(string) + d.Price, _ = data["price"].(float32) + ingredients, _ := data["ingredients"].([]map[string]interface{}) + for _, e := range ingredients { + n, _ := interface{}(e).(map[string]interface{}) + name, _ := n["name"].(string) + i := ingredient{name} + d.Ingredients = append(d.Ingredients, i) + } + return nil +} + +type ingredient struct { + Name string +} + +func ExampleMetaData_PrimitiveDecode() { + var md MetaData + var err error + + var tomlBlob = ` +ranking = ["Springsteen", "J Geils"] + +[bands.Springsteen] +started = 1973 +albums = ["Greetings", "WIESS", "Born to Run", "Darkness"] + +[bands."J Geils"] +started = 1970 +albums = ["The J. Geils Band", "Full House", "Blow Your Face Out"] +` + + type band struct { + Started int + Albums []string + } + type classics struct { + Ranking []string + Bands map[string]Primitive + } + + // Do the initial decode. Reflection is delayed on Primitive values. + var music classics + if md, err = Decode(tomlBlob, &music); err != nil { + log.Fatal(err) + } + + // MetaData still includes information on Primitive values. + fmt.Printf("Is `bands.Springsteen` defined? %v\n", + md.IsDefined("bands", "Springsteen")) + + // Decode primitive data into Go values. + for _, artist := range music.Ranking { + // A band is a primitive value, so we need to decode it to get a + // real `band` value. + primValue := music.Bands[artist] + + var aBand band + if err = md.PrimitiveDecode(primValue, &aBand); err != nil { + log.Fatal(err) + } + fmt.Printf("%s started in %d.\n", artist, aBand.Started) + } + // Check to see if there were any fields left undecoded. + // Note that this won't be empty before decoding the Primitive value! + fmt.Printf("Undecoded: %q\n", md.Undecoded()) + + // Output: + // Is `bands.Springsteen` defined? true + // Springsteen started in 1973. + // J Geils started in 1970. + // Undecoded: [] +} + +func ExampleDecode() { + var tomlBlob = ` +# Some comments. +[alpha] +ip = "10.0.0.1" + + [alpha.config] + Ports = [ 8001, 8002 ] + Location = "Toronto" + Created = 1987-07-05T05:45:00Z + +[beta] +ip = "10.0.0.2" + + [beta.config] + Ports = [ 9001, 9002 ] + Location = "New Jersey" + Created = 1887-01-05T05:55:00Z +` + + type serverConfig struct { + Ports []int + Location string + Created time.Time + } + + type server struct { + IP string `toml:"ip"` + Config serverConfig `toml:"config"` + } + + type servers map[string]server + + var config servers + if _, err := Decode(tomlBlob, &config); err != nil { + log.Fatal(err) + } + + for _, name := range []string{"alpha", "beta"} { + s := config[name] + fmt.Printf("Server: %s (ip: %s) in %s created on %s\n", + name, s.IP, s.Config.Location, + s.Config.Created.Format("2006-01-02")) + fmt.Printf("Ports: %v\n", s.Config.Ports) + } + + // Output: + // Server: alpha (ip: 10.0.0.1) in Toronto created on 1987-07-05 + // Ports: [8001 8002] + // Server: beta (ip: 10.0.0.2) in New Jersey created on 1887-01-05 + // Ports: [9001 9002] +} + +type duration struct { + time.Duration +} + +func (d *duration) UnmarshalText(text []byte) error { + var err error + d.Duration, err = time.ParseDuration(string(text)) + return err +} + +// Example Unmarshaler shows how to decode TOML strings into your own +// custom data type. +func Example_unmarshaler() { + blob := ` +[[song]] +name = "Thunder Road" +duration = "4m49s" + +[[song]] +name = "Stairway to Heaven" +duration = "8m03s" +` + type song struct { + Name string + Duration duration + } + type songs struct { + Song []song + } + var favorites songs + if _, err := Decode(blob, &favorites); err != nil { + log.Fatal(err) + } + + // Code to implement the TextUnmarshaler interface for `duration`: + // + // type duration struct { + // time.Duration + // } + // + // func (d *duration) UnmarshalText(text []byte) error { + // var err error + // d.Duration, err = time.ParseDuration(string(text)) + // return err + // } + + for _, s := range favorites.Song { + fmt.Printf("%s (%s)\n", s.Name, s.Duration) + } + // Output: + // Thunder Road (4m49s) + // Stairway to Heaven (8m3s) +} + +// Example StrictDecoding shows how to detect whether there are keys in the +// TOML document that weren't decoded into the value given. This is useful +// for returning an error to the user if they've included extraneous fields +// in their configuration. +func Example_strictDecoding() { + var blob = ` +key1 = "value1" +key2 = "value2" +key3 = "value3" +` + type config struct { + Key1 string + Key3 string + } + + var conf config + md, err := Decode(blob, &conf) + if err != nil { + log.Fatal(err) + } + fmt.Printf("Undecoded keys: %q\n", md.Undecoded()) + // Output: + // Undecoded keys: ["key2"] +} + +// Example UnmarshalTOML shows how to implement a struct type that knows how to +// unmarshal itself. The struct must take full responsibility for mapping the +// values passed into the struct. The method may be used with interfaces in a +// struct in cases where the actual type is not known until the data is +// examined. +func Example_unmarshalTOML() { + + var blob = ` +[[parts]] +type = "valve" +id = "valve-1" +size = 1.2 +rating = 4 + +[[parts]] +type = "valve" +id = "valve-2" +size = 2.1 +rating = 5 + +[[parts]] +type = "pipe" +id = "pipe-1" +length = 2.1 +diameter = 12 + +[[parts]] +type = "cable" +id = "cable-1" +length = 12 +rating = 3.1 +` + o := &order{} + err := Unmarshal([]byte(blob), o) + if err != nil { + log.Fatal(err) + } + + fmt.Println(len(o.parts)) + + for _, part := range o.parts { + fmt.Println(part.Name()) + } + + // Code to implement UmarshalJSON. + + // type order struct { + // // NOTE `order.parts` is a private slice of type `part` which is an + // // interface and may only be loaded from toml using the + // // UnmarshalTOML() method of the Umarshaler interface. + // parts parts + // } + + // func (o *order) UnmarshalTOML(data interface{}) error { + + // // NOTE the example below contains detailed type casting to show how + // // the 'data' is retrieved. In operational use, a type cast wrapper + // // may be prefered e.g. + // // + // // func AsMap(v interface{}) (map[string]interface{}, error) { + // // return v.(map[string]interface{}) + // // } + // // + // // resulting in: + // // d, _ := AsMap(data) + // // + + // d, _ := data.(map[string]interface{}) + // parts, _ := d["parts"].([]map[string]interface{}) + + // for _, p := range parts { + + // typ, _ := p["type"].(string) + // id, _ := p["id"].(string) + + // // detect the type of part and handle each case + // switch p["type"] { + // case "valve": + + // size := float32(p["size"].(float64)) + // rating := int(p["rating"].(int64)) + + // valve := &valve{ + // Type: typ, + // ID: id, + // Size: size, + // Rating: rating, + // } + + // o.parts = append(o.parts, valve) + + // case "pipe": + + // length := float32(p["length"].(float64)) + // diameter := int(p["diameter"].(int64)) + + // pipe := &pipe{ + // Type: typ, + // ID: id, + // Length: length, + // Diameter: diameter, + // } + + // o.parts = append(o.parts, pipe) + + // case "cable": + + // length := int(p["length"].(int64)) + // rating := float32(p["rating"].(float64)) + + // cable := &cable{ + // Type: typ, + // ID: id, + // Length: length, + // Rating: rating, + // } + + // o.parts = append(o.parts, cable) + + // } + // } + + // return nil + // } + + // type parts []part + + // type part interface { + // Name() string + // } + + // type valve struct { + // Type string + // ID string + // Size float32 + // Rating int + // } + + // func (v *valve) Name() string { + // return fmt.Sprintf("VALVE: %s", v.ID) + // } + + // type pipe struct { + // Type string + // ID string + // Length float32 + // Diameter int + // } + + // func (p *pipe) Name() string { + // return fmt.Sprintf("PIPE: %s", p.ID) + // } + + // type cable struct { + // Type string + // ID string + // Length int + // Rating float32 + // } + + // func (c *cable) Name() string { + // return fmt.Sprintf("CABLE: %s", c.ID) + // } + + // Output: + // 4 + // VALVE: valve-1 + // VALVE: valve-2 + // PIPE: pipe-1 + // CABLE: cable-1 + +} + +type order struct { + // NOTE `order.parts` is a private slice of type `part` which is an + // interface and may only be loaded from toml using the UnmarshalTOML() + // method of the Umarshaler interface. + parts parts +} + +func (o *order) UnmarshalTOML(data interface{}) error { + + // NOTE the example below contains detailed type casting to show how + // the 'data' is retrieved. In operational use, a type cast wrapper + // may be prefered e.g. + // + // func AsMap(v interface{}) (map[string]interface{}, error) { + // return v.(map[string]interface{}) + // } + // + // resulting in: + // d, _ := AsMap(data) + // + + d, _ := data.(map[string]interface{}) + parts, _ := d["parts"].([]map[string]interface{}) + + for _, p := range parts { + + typ, _ := p["type"].(string) + id, _ := p["id"].(string) + + // detect the type of part and handle each case + switch p["type"] { + case "valve": + + size := float32(p["size"].(float64)) + rating := int(p["rating"].(int64)) + + valve := &valve{ + Type: typ, + ID: id, + Size: size, + Rating: rating, + } + + o.parts = append(o.parts, valve) + + case "pipe": + + length := float32(p["length"].(float64)) + diameter := int(p["diameter"].(int64)) + + pipe := &pipe{ + Type: typ, + ID: id, + Length: length, + Diameter: diameter, + } + + o.parts = append(o.parts, pipe) + + case "cable": + + length := int(p["length"].(int64)) + rating := float32(p["rating"].(float64)) + + cable := &cable{ + Type: typ, + ID: id, + Length: length, + Rating: rating, + } + + o.parts = append(o.parts, cable) + + } + } + + return nil +} + +type parts []part + +type part interface { + Name() string +} + +type valve struct { + Type string + ID string + Size float32 + Rating int +} + +func (v *valve) Name() string { + return fmt.Sprintf("VALVE: %s", v.ID) +} + +type pipe struct { + Type string + ID string + Length float32 + Diameter int +} + +func (p *pipe) Name() string { + return fmt.Sprintf("PIPE: %s", p.ID) +} + +type cable struct { + Type string + ID string + Length int + Rating float32 +} + +func (c *cable) Name() string { + return fmt.Sprintf("CABLE: %s", c.ID) +} diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/doc.go b/Godeps/_workspace/src/github.com/BurntSushi/toml/doc.go new file mode 100644 index 00000000..fe268000 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/doc.go @@ -0,0 +1,27 @@ +/* +Package toml provides facilities for decoding and encoding TOML configuration +files via reflection. There is also support for delaying decoding with +the Primitive type, and querying the set of keys in a TOML document with the +MetaData type. + +The specification implemented: https://github.com/mojombo/toml + +The sub-command github.com/BurntSushi/toml/cmd/tomlv can be used to verify +whether a file is a valid TOML document. It can also be used to print the +type of each key in a TOML document. + +Testing + +There are two important types of tests used for this package. The first is +contained inside '*_test.go' files and uses the standard Go unit testing +framework. These tests are primarily devoted to holistically testing the +decoder and encoder. + +The second type of testing is used to verify the implementation's adherence +to the TOML specification. These tests have been factored into their own +project: https://github.com/BurntSushi/toml-test + +The reason the tests are in a separate project is so that they can be used by +any implementation of TOML. Namely, it is language agnostic. +*/ +package toml diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/encode.go b/Godeps/_workspace/src/github.com/BurntSushi/toml/encode.go new file mode 100644 index 00000000..c7e227c7 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/encode.go @@ -0,0 +1,551 @@ +package toml + +import ( + "bufio" + "errors" + "fmt" + "io" + "reflect" + "sort" + "strconv" + "strings" + "time" +) + +type tomlEncodeError struct{ error } + +var ( + errArrayMixedElementTypes = errors.New( + "can't encode array with mixed element types") + errArrayNilElement = errors.New( + "can't encode array with nil element") + errNonString = errors.New( + "can't encode a map with non-string key type") + errAnonNonStruct = errors.New( + "can't encode an anonymous field that is not a struct") + errArrayNoTable = errors.New( + "TOML array element can't contain a table") + errNoKey = errors.New( + "top-level values must be a Go map or struct") + errAnything = errors.New("") // used in testing +) + +var quotedReplacer = strings.NewReplacer( + "\t", "\\t", + "\n", "\\n", + "\r", "\\r", + "\"", "\\\"", + "\\", "\\\\", +) + +// Encoder controls the encoding of Go values to a TOML document to some +// io.Writer. +// +// The indentation level can be controlled with the Indent field. +type Encoder struct { + // A single indentation level. By default it is two spaces. + Indent string + + // hasWritten is whether we have written any output to w yet. + hasWritten bool + w *bufio.Writer +} + +// NewEncoder returns a TOML encoder that encodes Go values to the io.Writer +// given. By default, a single indentation level is 2 spaces. +func NewEncoder(w io.Writer) *Encoder { + return &Encoder{ + w: bufio.NewWriter(w), + Indent: " ", + } +} + +// Encode writes a TOML representation of the Go value to the underlying +// io.Writer. If the value given cannot be encoded to a valid TOML document, +// then an error is returned. +// +// The mapping between Go values and TOML values should be precisely the same +// as for the Decode* functions. Similarly, the TextMarshaler interface is +// supported by encoding the resulting bytes as strings. (If you want to write +// arbitrary binary data then you will need to use something like base64 since +// TOML does not have any binary types.) +// +// When encoding TOML hashes (i.e., Go maps or structs), keys without any +// sub-hashes are encoded first. +// +// If a Go map is encoded, then its keys are sorted alphabetically for +// deterministic output. More control over this behavior may be provided if +// there is demand for it. +// +// Encoding Go values without a corresponding TOML representation---like map +// types with non-string keys---will cause an error to be returned. Similarly +// for mixed arrays/slices, arrays/slices with nil elements, embedded +// non-struct types and nested slices containing maps or structs. +// (e.g., [][]map[string]string is not allowed but []map[string]string is OK +// and so is []map[string][]string.) +func (enc *Encoder) Encode(v interface{}) error { + rv := eindirect(reflect.ValueOf(v)) + if err := enc.safeEncode(Key([]string{}), rv); err != nil { + return err + } + return enc.w.Flush() +} + +func (enc *Encoder) safeEncode(key Key, rv reflect.Value) (err error) { + defer func() { + if r := recover(); r != nil { + if terr, ok := r.(tomlEncodeError); ok { + err = terr.error + return + } + panic(r) + } + }() + enc.encode(key, rv) + return nil +} + +func (enc *Encoder) encode(key Key, rv reflect.Value) { + // Special case. Time needs to be in ISO8601 format. + // Special case. If we can marshal the type to text, then we used that. + // Basically, this prevents the encoder for handling these types as + // generic structs (or whatever the underlying type of a TextMarshaler is). + switch rv.Interface().(type) { + case time.Time, TextMarshaler: + enc.keyEqElement(key, rv) + return + } + + k := rv.Kind() + switch k { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, + reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, + reflect.Uint64, + reflect.Float32, reflect.Float64, reflect.String, reflect.Bool: + enc.keyEqElement(key, rv) + case reflect.Array, reflect.Slice: + if typeEqual(tomlArrayHash, tomlTypeOfGo(rv)) { + enc.eArrayOfTables(key, rv) + } else { + enc.keyEqElement(key, rv) + } + case reflect.Interface: + if rv.IsNil() { + return + } + enc.encode(key, rv.Elem()) + case reflect.Map: + if rv.IsNil() { + return + } + enc.eTable(key, rv) + case reflect.Ptr: + if rv.IsNil() { + return + } + enc.encode(key, rv.Elem()) + case reflect.Struct: + enc.eTable(key, rv) + default: + panic(e("Unsupported type for key '%s': %s", key, k)) + } +} + +// eElement encodes any value that can be an array element (primitives and +// arrays). +func (enc *Encoder) eElement(rv reflect.Value) { + switch v := rv.Interface().(type) { + case time.Time: + // Special case time.Time as a primitive. Has to come before + // TextMarshaler below because time.Time implements + // encoding.TextMarshaler, but we need to always use UTC. + enc.wf(v.In(time.FixedZone("UTC", 0)).Format("2006-01-02T15:04:05Z")) + return + case TextMarshaler: + // Special case. Use text marshaler if it's available for this value. + if s, err := v.MarshalText(); err != nil { + encPanic(err) + } else { + enc.writeQuoted(string(s)) + } + return + } + switch rv.Kind() { + case reflect.Bool: + enc.wf(strconv.FormatBool(rv.Bool())) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, + reflect.Int64: + enc.wf(strconv.FormatInt(rv.Int(), 10)) + case reflect.Uint, reflect.Uint8, reflect.Uint16, + reflect.Uint32, reflect.Uint64: + enc.wf(strconv.FormatUint(rv.Uint(), 10)) + case reflect.Float32: + enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 32))) + case reflect.Float64: + enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 64))) + case reflect.Array, reflect.Slice: + enc.eArrayOrSliceElement(rv) + case reflect.Interface: + enc.eElement(rv.Elem()) + case reflect.String: + enc.writeQuoted(rv.String()) + default: + panic(e("Unexpected primitive type: %s", rv.Kind())) + } +} + +// By the TOML spec, all floats must have a decimal with at least one +// number on either side. +func floatAddDecimal(fstr string) string { + if !strings.Contains(fstr, ".") { + return fstr + ".0" + } + return fstr +} + +func (enc *Encoder) writeQuoted(s string) { + enc.wf("\"%s\"", quotedReplacer.Replace(s)) +} + +func (enc *Encoder) eArrayOrSliceElement(rv reflect.Value) { + length := rv.Len() + enc.wf("[") + for i := 0; i < length; i++ { + elem := rv.Index(i) + enc.eElement(elem) + if i != length-1 { + enc.wf(", ") + } + } + enc.wf("]") +} + +func (enc *Encoder) eArrayOfTables(key Key, rv reflect.Value) { + if len(key) == 0 { + encPanic(errNoKey) + } + for i := 0; i < rv.Len(); i++ { + trv := rv.Index(i) + if isNil(trv) { + continue + } + panicIfInvalidKey(key) + enc.newline() + enc.wf("%s[[%s]]", enc.indentStr(key), key.maybeQuotedAll()) + enc.newline() + enc.eMapOrStruct(key, trv) + } +} + +func (enc *Encoder) eTable(key Key, rv reflect.Value) { + panicIfInvalidKey(key) + if len(key) == 1 { + // Output an extra new line between top-level tables. + // (The newline isn't written if nothing else has been written though.) + enc.newline() + } + if len(key) > 0 { + enc.wf("%s[%s]", enc.indentStr(key), key.maybeQuotedAll()) + enc.newline() + } + enc.eMapOrStruct(key, rv) +} + +func (enc *Encoder) eMapOrStruct(key Key, rv reflect.Value) { + switch rv := eindirect(rv); rv.Kind() { + case reflect.Map: + enc.eMap(key, rv) + case reflect.Struct: + enc.eStruct(key, rv) + default: + panic("eTable: unhandled reflect.Value Kind: " + rv.Kind().String()) + } +} + +func (enc *Encoder) eMap(key Key, rv reflect.Value) { + rt := rv.Type() + if rt.Key().Kind() != reflect.String { + encPanic(errNonString) + } + + // Sort keys so that we have deterministic output. And write keys directly + // underneath this key first, before writing sub-structs or sub-maps. + var mapKeysDirect, mapKeysSub []string + for _, mapKey := range rv.MapKeys() { + k := mapKey.String() + if typeIsHash(tomlTypeOfGo(rv.MapIndex(mapKey))) { + mapKeysSub = append(mapKeysSub, k) + } else { + mapKeysDirect = append(mapKeysDirect, k) + } + } + + var writeMapKeys = func(mapKeys []string) { + sort.Strings(mapKeys) + for _, mapKey := range mapKeys { + mrv := rv.MapIndex(reflect.ValueOf(mapKey)) + if isNil(mrv) { + // Don't write anything for nil fields. + continue + } + enc.encode(key.add(mapKey), mrv) + } + } + writeMapKeys(mapKeysDirect) + writeMapKeys(mapKeysSub) +} + +func (enc *Encoder) eStruct(key Key, rv reflect.Value) { + // Write keys for fields directly under this key first, because if we write + // a field that creates a new table, then all keys under it will be in that + // table (not the one we're writing here). + rt := rv.Type() + var fieldsDirect, fieldsSub [][]int + var addFields func(rt reflect.Type, rv reflect.Value, start []int) + addFields = func(rt reflect.Type, rv reflect.Value, start []int) { + for i := 0; i < rt.NumField(); i++ { + f := rt.Field(i) + // skip unexporded fields + if f.PkgPath != "" { + continue + } + frv := rv.Field(i) + if f.Anonymous { + frv := eindirect(frv) + t := frv.Type() + if t.Kind() != reflect.Struct { + encPanic(errAnonNonStruct) + } + addFields(t, frv, f.Index) + } else if typeIsHash(tomlTypeOfGo(frv)) { + fieldsSub = append(fieldsSub, append(start, f.Index...)) + } else { + fieldsDirect = append(fieldsDirect, append(start, f.Index...)) + } + } + } + addFields(rt, rv, nil) + + var writeFields = func(fields [][]int) { + for _, fieldIndex := range fields { + sft := rt.FieldByIndex(fieldIndex) + sf := rv.FieldByIndex(fieldIndex) + if isNil(sf) { + // Don't write anything for nil fields. + continue + } + + keyName := sft.Tag.Get("toml") + if keyName == "-" { + continue + } + if keyName == "" { + keyName = sft.Name + } + + keyName, opts := getOptions(keyName) + if _, ok := opts["omitempty"]; ok && isEmpty(sf) { + continue + } else if _, ok := opts["omitzero"]; ok && isZero(sf) { + continue + } + + enc.encode(key.add(keyName), sf) + } + } + writeFields(fieldsDirect) + writeFields(fieldsSub) +} + +// tomlTypeName returns the TOML type name of the Go value's type. It is +// used to determine whether the types of array elements are mixed (which is +// forbidden). If the Go value is nil, then it is illegal for it to be an array +// element, and valueIsNil is returned as true. + +// Returns the TOML type of a Go value. The type may be `nil`, which means +// no concrete TOML type could be found. +func tomlTypeOfGo(rv reflect.Value) tomlType { + if isNil(rv) || !rv.IsValid() { + return nil + } + switch rv.Kind() { + case reflect.Bool: + return tomlBool + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, + reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, + reflect.Uint64: + return tomlInteger + case reflect.Float32, reflect.Float64: + return tomlFloat + case reflect.Array, reflect.Slice: + if typeEqual(tomlHash, tomlArrayType(rv)) { + return tomlArrayHash + } else { + return tomlArray + } + case reflect.Ptr, reflect.Interface: + return tomlTypeOfGo(rv.Elem()) + case reflect.String: + return tomlString + case reflect.Map: + return tomlHash + case reflect.Struct: + switch rv.Interface().(type) { + case time.Time: + return tomlDatetime + case TextMarshaler: + return tomlString + default: + return tomlHash + } + default: + panic("unexpected reflect.Kind: " + rv.Kind().String()) + } +} + +// tomlArrayType returns the element type of a TOML array. The type returned +// may be nil if it cannot be determined (e.g., a nil slice or a zero length +// slize). This function may also panic if it finds a type that cannot be +// expressed in TOML (such as nil elements, heterogeneous arrays or directly +// nested arrays of tables). +func tomlArrayType(rv reflect.Value) tomlType { + if isNil(rv) || !rv.IsValid() || rv.Len() == 0 { + return nil + } + firstType := tomlTypeOfGo(rv.Index(0)) + if firstType == nil { + encPanic(errArrayNilElement) + } + + rvlen := rv.Len() + for i := 1; i < rvlen; i++ { + elem := rv.Index(i) + switch elemType := tomlTypeOfGo(elem); { + case elemType == nil: + encPanic(errArrayNilElement) + case !typeEqual(firstType, elemType): + encPanic(errArrayMixedElementTypes) + } + } + // If we have a nested array, then we must make sure that the nested + // array contains ONLY primitives. + // This checks arbitrarily nested arrays. + if typeEqual(firstType, tomlArray) || typeEqual(firstType, tomlArrayHash) { + nest := tomlArrayType(eindirect(rv.Index(0))) + if typeEqual(nest, tomlHash) || typeEqual(nest, tomlArrayHash) { + encPanic(errArrayNoTable) + } + } + return firstType +} + +func getOptions(keyName string) (string, map[string]struct{}) { + opts := make(map[string]struct{}) + ss := strings.Split(keyName, ",") + name := ss[0] + if len(ss) > 1 { + for _, opt := range ss { + opts[opt] = struct{}{} + } + } + + return name, opts +} + +func isZero(rv reflect.Value) bool { + switch rv.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if rv.Int() == 0 { + return true + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if rv.Uint() == 0 { + return true + } + case reflect.Float32, reflect.Float64: + if rv.Float() == 0.0 { + return true + } + } + + return false +} + +func isEmpty(rv reflect.Value) bool { + switch rv.Kind() { + case reflect.String: + if len(strings.TrimSpace(rv.String())) == 0 { + return true + } + case reflect.Array, reflect.Slice, reflect.Map: + if rv.Len() == 0 { + return true + } + } + + return false +} + +func (enc *Encoder) newline() { + if enc.hasWritten { + enc.wf("\n") + } +} + +func (enc *Encoder) keyEqElement(key Key, val reflect.Value) { + if len(key) == 0 { + encPanic(errNoKey) + } + panicIfInvalidKey(key) + enc.wf("%s%s = ", enc.indentStr(key), key.maybeQuoted(len(key)-1)) + enc.eElement(val) + enc.newline() +} + +func (enc *Encoder) wf(format string, v ...interface{}) { + if _, err := fmt.Fprintf(enc.w, format, v...); err != nil { + encPanic(err) + } + enc.hasWritten = true +} + +func (enc *Encoder) indentStr(key Key) string { + return strings.Repeat(enc.Indent, len(key)-1) +} + +func encPanic(err error) { + panic(tomlEncodeError{err}) +} + +func eindirect(v reflect.Value) reflect.Value { + switch v.Kind() { + case reflect.Ptr, reflect.Interface: + return eindirect(v.Elem()) + default: + return v + } +} + +func isNil(rv reflect.Value) bool { + switch rv.Kind() { + case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: + return rv.IsNil() + default: + return false + } +} + +func panicIfInvalidKey(key Key) { + for _, k := range key { + if len(k) == 0 { + encPanic(e("Key '%s' is not a valid table name. Key names "+ + "cannot be empty.", key.maybeQuotedAll())) + } + } +} + +func isValidKeyName(s string) bool { + return len(s) != 0 +} diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/encode_test.go b/Godeps/_workspace/src/github.com/BurntSushi/toml/encode_test.go new file mode 100644 index 00000000..445ca8e2 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/encode_test.go @@ -0,0 +1,542 @@ +package toml + +import ( + "bytes" + "fmt" + "log" + "net" + "testing" + "time" +) + +func TestEncodeRoundTrip(t *testing.T) { + type Config struct { + Age int + Cats []string + Pi float64 + Perfection []int + DOB time.Time + Ipaddress net.IP + } + + var inputs = Config{ + 13, + []string{"one", "two", "three"}, + 3.145, + []int{11, 2, 3, 4}, + time.Now(), + net.ParseIP("192.168.59.254"), + } + + var firstBuffer bytes.Buffer + e := NewEncoder(&firstBuffer) + err := e.Encode(inputs) + if err != nil { + t.Fatal(err) + } + var outputs Config + if _, err := Decode(firstBuffer.String(), &outputs); err != nil { + log.Printf("Could not decode:\n-----\n%s\n-----\n", + firstBuffer.String()) + t.Fatal(err) + } + + // could test each value individually, but I'm lazy + var secondBuffer bytes.Buffer + e2 := NewEncoder(&secondBuffer) + err = e2.Encode(outputs) + if err != nil { + t.Fatal(err) + } + if firstBuffer.String() != secondBuffer.String() { + t.Error( + firstBuffer.String(), + "\n\n is not identical to\n\n", + secondBuffer.String()) + } +} + +// XXX(burntsushi) +// I think these tests probably should be removed. They are good, but they +// ought to be obsolete by toml-test. +func TestEncode(t *testing.T) { + type Embedded struct { + Int int `toml:"_int"` + } + type NonStruct int + + date := time.Date(2014, 5, 11, 20, 30, 40, 0, time.FixedZone("IST", 3600)) + dateStr := "2014-05-11T19:30:40Z" + + tests := map[string]struct { + input interface{} + wantOutput string + wantError error + }{ + "bool field": { + input: struct { + BoolTrue bool + BoolFalse bool + }{true, false}, + wantOutput: "BoolTrue = true\nBoolFalse = false\n", + }, + "int fields": { + input: struct { + Int int + Int8 int8 + Int16 int16 + Int32 int32 + Int64 int64 + }{1, 2, 3, 4, 5}, + wantOutput: "Int = 1\nInt8 = 2\nInt16 = 3\nInt32 = 4\nInt64 = 5\n", + }, + "uint fields": { + input: struct { + Uint uint + Uint8 uint8 + Uint16 uint16 + Uint32 uint32 + Uint64 uint64 + }{1, 2, 3, 4, 5}, + wantOutput: "Uint = 1\nUint8 = 2\nUint16 = 3\nUint32 = 4" + + "\nUint64 = 5\n", + }, + "float fields": { + input: struct { + Float32 float32 + Float64 float64 + }{1.5, 2.5}, + wantOutput: "Float32 = 1.5\nFloat64 = 2.5\n", + }, + "string field": { + input: struct{ String string }{"foo"}, + wantOutput: "String = \"foo\"\n", + }, + "string field and unexported field": { + input: struct { + String string + unexported int + }{"foo", 0}, + wantOutput: "String = \"foo\"\n", + }, + "datetime field in UTC": { + input: struct{ Date time.Time }{date}, + wantOutput: fmt.Sprintf("Date = %s\n", dateStr), + }, + "datetime field as primitive": { + // Using a map here to fail if isStructOrMap() returns true for + // time.Time. + input: map[string]interface{}{ + "Date": date, + "Int": 1, + }, + wantOutput: fmt.Sprintf("Date = %s\nInt = 1\n", dateStr), + }, + "array fields": { + input: struct { + IntArray0 [0]int + IntArray3 [3]int + }{[0]int{}, [3]int{1, 2, 3}}, + wantOutput: "IntArray0 = []\nIntArray3 = [1, 2, 3]\n", + }, + "slice fields": { + input: struct{ IntSliceNil, IntSlice0, IntSlice3 []int }{ + nil, []int{}, []int{1, 2, 3}, + }, + wantOutput: "IntSlice0 = []\nIntSlice3 = [1, 2, 3]\n", + }, + "datetime slices": { + input: struct{ DatetimeSlice []time.Time }{ + []time.Time{date, date}, + }, + wantOutput: fmt.Sprintf("DatetimeSlice = [%s, %s]\n", + dateStr, dateStr), + }, + "nested arrays and slices": { + input: struct { + SliceOfArrays [][2]int + ArrayOfSlices [2][]int + SliceOfArraysOfSlices [][2][]int + ArrayOfSlicesOfArrays [2][][2]int + SliceOfMixedArrays [][2]interface{} + ArrayOfMixedSlices [2][]interface{} + }{ + [][2]int{{1, 2}, {3, 4}}, + [2][]int{{1, 2}, {3, 4}}, + [][2][]int{ + { + {1, 2}, {3, 4}, + }, + { + {5, 6}, {7, 8}, + }, + }, + [2][][2]int{ + { + {1, 2}, {3, 4}, + }, + { + {5, 6}, {7, 8}, + }, + }, + [][2]interface{}{ + {1, 2}, {"a", "b"}, + }, + [2][]interface{}{ + {1, 2}, {"a", "b"}, + }, + }, + wantOutput: `SliceOfArrays = [[1, 2], [3, 4]] +ArrayOfSlices = [[1, 2], [3, 4]] +SliceOfArraysOfSlices = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]] +ArrayOfSlicesOfArrays = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]] +SliceOfMixedArrays = [[1, 2], ["a", "b"]] +ArrayOfMixedSlices = [[1, 2], ["a", "b"]] +`, + }, + "empty slice": { + input: struct{ Empty []interface{} }{[]interface{}{}}, + wantOutput: "Empty = []\n", + }, + "(error) slice with element type mismatch (string and integer)": { + input: struct{ Mixed []interface{} }{[]interface{}{1, "a"}}, + wantError: errArrayMixedElementTypes, + }, + "(error) slice with element type mismatch (integer and float)": { + input: struct{ Mixed []interface{} }{[]interface{}{1, 2.5}}, + wantError: errArrayMixedElementTypes, + }, + "slice with elems of differing Go types, same TOML types": { + input: struct { + MixedInts []interface{} + MixedFloats []interface{} + }{ + []interface{}{ + int(1), int8(2), int16(3), int32(4), int64(5), + uint(1), uint8(2), uint16(3), uint32(4), uint64(5), + }, + []interface{}{float32(1.5), float64(2.5)}, + }, + wantOutput: "MixedInts = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]\n" + + "MixedFloats = [1.5, 2.5]\n", + }, + "(error) slice w/ element type mismatch (one is nested array)": { + input: struct{ Mixed []interface{} }{ + []interface{}{1, []interface{}{2}}, + }, + wantError: errArrayMixedElementTypes, + }, + "(error) slice with 1 nil element": { + input: struct{ NilElement1 []interface{} }{[]interface{}{nil}}, + wantError: errArrayNilElement, + }, + "(error) slice with 1 nil element (and other non-nil elements)": { + input: struct{ NilElement []interface{} }{ + []interface{}{1, nil}, + }, + wantError: errArrayNilElement, + }, + "simple map": { + input: map[string]int{"a": 1, "b": 2}, + wantOutput: "a = 1\nb = 2\n", + }, + "map with interface{} value type": { + input: map[string]interface{}{"a": 1, "b": "c"}, + wantOutput: "a = 1\nb = \"c\"\n", + }, + "map with interface{} value type, some of which are structs": { + input: map[string]interface{}{ + "a": struct{ Int int }{2}, + "b": 1, + }, + wantOutput: "b = 1\n\n[a]\n Int = 2\n", + }, + "nested map": { + input: map[string]map[string]int{ + "a": {"b": 1}, + "c": {"d": 2}, + }, + wantOutput: "[a]\n b = 1\n\n[c]\n d = 2\n", + }, + "nested struct": { + input: struct{ Struct struct{ Int int } }{ + struct{ Int int }{1}, + }, + wantOutput: "[Struct]\n Int = 1\n", + }, + "nested struct and non-struct field": { + input: struct { + Struct struct{ Int int } + Bool bool + }{struct{ Int int }{1}, true}, + wantOutput: "Bool = true\n\n[Struct]\n Int = 1\n", + }, + "2 nested structs": { + input: struct{ Struct1, Struct2 struct{ Int int } }{ + struct{ Int int }{1}, struct{ Int int }{2}, + }, + wantOutput: "[Struct1]\n Int = 1\n\n[Struct2]\n Int = 2\n", + }, + "deeply nested structs": { + input: struct { + Struct1, Struct2 struct{ Struct3 *struct{ Int int } } + }{ + struct{ Struct3 *struct{ Int int } }{&struct{ Int int }{1}}, + struct{ Struct3 *struct{ Int int } }{nil}, + }, + wantOutput: "[Struct1]\n [Struct1.Struct3]\n Int = 1" + + "\n\n[Struct2]\n", + }, + "nested struct with nil struct elem": { + input: struct { + Struct struct{ Inner *struct{ Int int } } + }{ + struct{ Inner *struct{ Int int } }{nil}, + }, + wantOutput: "[Struct]\n", + }, + "nested struct with no fields": { + input: struct { + Struct struct{ Inner struct{} } + }{ + struct{ Inner struct{} }{struct{}{}}, + }, + wantOutput: "[Struct]\n [Struct.Inner]\n", + }, + "struct with tags": { + input: struct { + Struct struct { + Int int `toml:"_int"` + } `toml:"_struct"` + Bool bool `toml:"_bool"` + }{ + struct { + Int int `toml:"_int"` + }{1}, true, + }, + wantOutput: "_bool = true\n\n[_struct]\n _int = 1\n", + }, + "embedded struct": { + input: struct{ Embedded }{Embedded{1}}, + wantOutput: "_int = 1\n", + }, + "embedded *struct": { + input: struct{ *Embedded }{&Embedded{1}}, + wantOutput: "_int = 1\n", + }, + "nested embedded struct": { + input: struct { + Struct struct{ Embedded } `toml:"_struct"` + }{struct{ Embedded }{Embedded{1}}}, + wantOutput: "[_struct]\n _int = 1\n", + }, + "nested embedded *struct": { + input: struct { + Struct struct{ *Embedded } `toml:"_struct"` + }{struct{ *Embedded }{&Embedded{1}}}, + wantOutput: "[_struct]\n _int = 1\n", + }, + "array of tables": { + input: struct { + Structs []*struct{ Int int } `toml:"struct"` + }{ + []*struct{ Int int }{{1}, {3}}, + }, + wantOutput: "[[struct]]\n Int = 1\n\n[[struct]]\n Int = 3\n", + }, + "array of tables order": { + input: map[string]interface{}{ + "map": map[string]interface{}{ + "zero": 5, + "arr": []map[string]int{ + map[string]int{ + "friend": 5, + }, + }, + }, + }, + wantOutput: "[map]\n zero = 5\n\n [[map.arr]]\n friend = 5\n", + }, + "(error) top-level slice": { + input: []struct{ Int int }{{1}, {2}, {3}}, + wantError: errNoKey, + }, + "(error) slice of slice": { + input: struct { + Slices [][]struct{ Int int } + }{ + [][]struct{ Int int }{{{1}}, {{2}}, {{3}}}, + }, + wantError: errArrayNoTable, + }, + "(error) map no string key": { + input: map[int]string{1: ""}, + wantError: errNonString, + }, + "(error) anonymous non-struct": { + input: struct{ NonStruct }{5}, + wantError: errAnonNonStruct, + }, + "(error) empty key name": { + input: map[string]int{"": 1}, + wantError: errAnything, + }, + "(error) empty map name": { + input: map[string]interface{}{ + "": map[string]int{"v": 1}, + }, + wantError: errAnything, + }, + } + for label, test := range tests { + encodeExpected(t, label, test.input, test.wantOutput, test.wantError) + } +} + +func TestEncodeNestedTableArrays(t *testing.T) { + type song struct { + Name string `toml:"name"` + } + type album struct { + Name string `toml:"name"` + Songs []song `toml:"songs"` + } + type springsteen struct { + Albums []album `toml:"albums"` + } + value := springsteen{ + []album{ + {"Born to Run", + []song{{"Jungleland"}, {"Meeting Across the River"}}}, + {"Born in the USA", + []song{{"Glory Days"}, {"Dancing in the Dark"}}}, + }, + } + expected := `[[albums]] + name = "Born to Run" + + [[albums.songs]] + name = "Jungleland" + + [[albums.songs]] + name = "Meeting Across the River" + +[[albums]] + name = "Born in the USA" + + [[albums.songs]] + name = "Glory Days" + + [[albums.songs]] + name = "Dancing in the Dark" +` + encodeExpected(t, "nested table arrays", value, expected, nil) +} + +func TestEncodeArrayHashWithNormalHashOrder(t *testing.T) { + type Alpha struct { + V int + } + type Beta struct { + V int + } + type Conf struct { + V int + A Alpha + B []Beta + } + + val := Conf{ + V: 1, + A: Alpha{2}, + B: []Beta{{3}}, + } + expected := "V = 1\n\n[A]\n V = 2\n\n[[B]]\n V = 3\n" + encodeExpected(t, "array hash with normal hash order", val, expected, nil) +} + +func TestEncodeWithOmitEmpty(t *testing.T) { + type simple struct { + User string `toml:"user"` + Pass string `toml:"password,omitempty"` + } + + value := simple{"Testing", ""} + expected := fmt.Sprintf("user = %q\n", value.User) + encodeExpected(t, "simple with omitempty, is empty", value, expected, nil) + value.Pass = "some password" + expected = fmt.Sprintf("user = %q\npassword = %q\n", value.User, value.Pass) + encodeExpected(t, "simple with omitempty, not empty", value, expected, nil) +} + +func TestEncodeWithOmitZero(t *testing.T) { + type simple struct { + Number int `toml:"number,omitzero"` + Real float64 `toml:"real,omitzero"` + Unsigned uint `toml:"unsigned,omitzero"` + } + + value := simple{0, 0.0, uint(0)} + expected := "" + + encodeExpected(t, "simple with omitzero, all zero", value, expected, nil) + + value.Number = 10 + value.Real = 20 + value.Unsigned = 5 + expected = `number = 10 +real = 20.0 +unsigned = 5 +` + encodeExpected(t, "simple with omitzero, non-zero", value, expected, nil) +} + +func encodeExpected( + t *testing.T, label string, val interface{}, wantStr string, wantErr error, +) { + var buf bytes.Buffer + enc := NewEncoder(&buf) + err := enc.Encode(val) + if err != wantErr { + if wantErr != nil { + if wantErr == errAnything && err != nil { + return + } + t.Errorf("%s: want Encode error %v, got %v", label, wantErr, err) + } else { + t.Errorf("%s: Encode failed: %s", label, err) + } + } + if err != nil { + return + } + if got := buf.String(); wantStr != got { + t.Errorf("%s: want\n-----\n%q\n-----\nbut got\n-----\n%q\n-----\n", + label, wantStr, got) + } +} + +func ExampleEncoder_Encode() { + date, _ := time.Parse(time.RFC822, "14 Mar 10 18:00 UTC") + var config = map[string]interface{}{ + "date": date, + "counts": []int{1, 1, 2, 3, 5, 8}, + "hash": map[string]string{ + "key1": "val1", + "key2": "val2", + }, + } + buf := new(bytes.Buffer) + if err := NewEncoder(buf).Encode(config); err != nil { + log.Fatal(err) + } + fmt.Println(buf.String()) + + // Output: + // counts = [1, 1, 2, 3, 5, 8] + // date = 2010-03-14T18:00:00Z + // + // [hash] + // key1 = "val1" + // key2 = "val2" +} diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/encoding_types.go b/Godeps/_workspace/src/github.com/BurntSushi/toml/encoding_types.go new file mode 100644 index 00000000..d36e1dd6 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/encoding_types.go @@ -0,0 +1,19 @@ +// +build go1.2 + +package toml + +// In order to support Go 1.1, we define our own TextMarshaler and +// TextUnmarshaler types. For Go 1.2+, we just alias them with the +// standard library interfaces. + +import ( + "encoding" +) + +// TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here +// so that Go 1.1 can be supported. +type TextMarshaler encoding.TextMarshaler + +// TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined +// here so that Go 1.1 can be supported. +type TextUnmarshaler encoding.TextUnmarshaler diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/encoding_types_1.1.go b/Godeps/_workspace/src/github.com/BurntSushi/toml/encoding_types_1.1.go new file mode 100644 index 00000000..e8d503d0 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/encoding_types_1.1.go @@ -0,0 +1,18 @@ +// +build !go1.2 + +package toml + +// These interfaces were introduced in Go 1.2, so we add them manually when +// compiling for Go 1.1. + +// TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here +// so that Go 1.1 can be supported. +type TextMarshaler interface { + MarshalText() (text []byte, err error) +} + +// TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined +// here so that Go 1.1 can be supported. +type TextUnmarshaler interface { + UnmarshalText(text []byte) error +} diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/lex.go b/Godeps/_workspace/src/github.com/BurntSushi/toml/lex.go new file mode 100644 index 00000000..21912285 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/lex.go @@ -0,0 +1,874 @@ +package toml + +import ( + "fmt" + "strings" + "unicode/utf8" +) + +type itemType int + +const ( + itemError itemType = iota + itemNIL // used in the parser to indicate no type + itemEOF + itemText + itemString + itemRawString + itemMultilineString + itemRawMultilineString + itemBool + itemInteger + itemFloat + itemDatetime + itemArray // the start of an array + itemArrayEnd + itemTableStart + itemTableEnd + itemArrayTableStart + itemArrayTableEnd + itemKeyStart + itemCommentStart +) + +const ( + eof = 0 + tableStart = '[' + tableEnd = ']' + arrayTableStart = '[' + arrayTableEnd = ']' + tableSep = '.' + keySep = '=' + arrayStart = '[' + arrayEnd = ']' + arrayValTerm = ',' + commentStart = '#' + stringStart = '"' + stringEnd = '"' + rawStringStart = '\'' + rawStringEnd = '\'' +) + +type stateFn func(lx *lexer) stateFn + +type lexer struct { + input string + start int + pos int + width int + line int + state stateFn + items chan item + + // A stack of state functions used to maintain context. + // The idea is to reuse parts of the state machine in various places. + // For example, values can appear at the top level or within arbitrarily + // nested arrays. The last state on the stack is used after a value has + // been lexed. Similarly for comments. + stack []stateFn +} + +type item struct { + typ itemType + val string + line int +} + +func (lx *lexer) nextItem() item { + for { + select { + case item := <-lx.items: + return item + default: + lx.state = lx.state(lx) + } + } +} + +func lex(input string) *lexer { + lx := &lexer{ + input: input + "\n", + state: lexTop, + line: 1, + items: make(chan item, 10), + stack: make([]stateFn, 0, 10), + } + return lx +} + +func (lx *lexer) push(state stateFn) { + lx.stack = append(lx.stack, state) +} + +func (lx *lexer) pop() stateFn { + if len(lx.stack) == 0 { + return lx.errorf("BUG in lexer: no states to pop.") + } + last := lx.stack[len(lx.stack)-1] + lx.stack = lx.stack[0 : len(lx.stack)-1] + return last +} + +func (lx *lexer) current() string { + return lx.input[lx.start:lx.pos] +} + +func (lx *lexer) emit(typ itemType) { + lx.items <- item{typ, lx.current(), lx.line} + lx.start = lx.pos +} + +func (lx *lexer) emitTrim(typ itemType) { + lx.items <- item{typ, strings.TrimSpace(lx.current()), lx.line} + lx.start = lx.pos +} + +func (lx *lexer) next() (r rune) { + if lx.pos >= len(lx.input) { + lx.width = 0 + return eof + } + + if lx.input[lx.pos] == '\n' { + lx.line++ + } + r, lx.width = utf8.DecodeRuneInString(lx.input[lx.pos:]) + lx.pos += lx.width + return r +} + +// ignore skips over the pending input before this point. +func (lx *lexer) ignore() { + lx.start = lx.pos +} + +// backup steps back one rune. Can be called only once per call of next. +func (lx *lexer) backup() { + lx.pos -= lx.width + if lx.pos < len(lx.input) && lx.input[lx.pos] == '\n' { + lx.line-- + } +} + +// accept consumes the next rune if it's equal to `valid`. +func (lx *lexer) accept(valid rune) bool { + if lx.next() == valid { + return true + } + lx.backup() + return false +} + +// peek returns but does not consume the next rune in the input. +func (lx *lexer) peek() rune { + r := lx.next() + lx.backup() + return r +} + +// errorf stops all lexing by emitting an error and returning `nil`. +// Note that any value that is a character is escaped if it's a special +// character (new lines, tabs, etc.). +func (lx *lexer) errorf(format string, values ...interface{}) stateFn { + lx.items <- item{ + itemError, + fmt.Sprintf(format, values...), + lx.line, + } + return nil +} + +// lexTop consumes elements at the top level of TOML data. +func lexTop(lx *lexer) stateFn { + r := lx.next() + if isWhitespace(r) || isNL(r) { + return lexSkip(lx, lexTop) + } + + switch r { + case commentStart: + lx.push(lexTop) + return lexCommentStart + case tableStart: + return lexTableStart + case eof: + if lx.pos > lx.start { + return lx.errorf("Unexpected EOF.") + } + lx.emit(itemEOF) + return nil + } + + // At this point, the only valid item can be a key, so we back up + // and let the key lexer do the rest. + lx.backup() + lx.push(lexTopEnd) + return lexKeyStart +} + +// lexTopEnd is entered whenever a top-level item has been consumed. (A value +// or a table.) It must see only whitespace, and will turn back to lexTop +// upon a new line. If it sees EOF, it will quit the lexer successfully. +func lexTopEnd(lx *lexer) stateFn { + r := lx.next() + switch { + case r == commentStart: + // a comment will read to a new line for us. + lx.push(lexTop) + return lexCommentStart + case isWhitespace(r): + return lexTopEnd + case isNL(r): + lx.ignore() + return lexTop + case r == eof: + lx.ignore() + return lexTop + } + return lx.errorf("Expected a top-level item to end with a new line, "+ + "comment or EOF, but got %q instead.", r) +} + +// lexTable lexes the beginning of a table. Namely, it makes sure that +// it starts with a character other than '.' and ']'. +// It assumes that '[' has already been consumed. +// It also handles the case that this is an item in an array of tables. +// e.g., '[[name]]'. +func lexTableStart(lx *lexer) stateFn { + if lx.peek() == arrayTableStart { + lx.next() + lx.emit(itemArrayTableStart) + lx.push(lexArrayTableEnd) + } else { + lx.emit(itemTableStart) + lx.push(lexTableEnd) + } + return lexTableNameStart +} + +func lexTableEnd(lx *lexer) stateFn { + lx.emit(itemTableEnd) + return lexTopEnd +} + +func lexArrayTableEnd(lx *lexer) stateFn { + if r := lx.next(); r != arrayTableEnd { + return lx.errorf("Expected end of table array name delimiter %q, "+ + "but got %q instead.", arrayTableEnd, r) + } + lx.emit(itemArrayTableEnd) + return lexTopEnd +} + +func lexTableNameStart(lx *lexer) stateFn { + switch r := lx.peek(); { + case r == tableEnd || r == eof: + return lx.errorf("Unexpected end of table name. (Table names cannot " + + "be empty.)") + case r == tableSep: + return lx.errorf("Unexpected table separator. (Table names cannot " + + "be empty.)") + case r == stringStart || r == rawStringStart: + lx.ignore() + lx.push(lexTableNameEnd) + return lexValue // reuse string lexing + case isWhitespace(r): + return lexTableNameStart + default: + return lexBareTableName + } +} + +// lexTableName lexes the name of a table. It assumes that at least one +// valid character for the table has already been read. +func lexBareTableName(lx *lexer) stateFn { + switch r := lx.next(); { + case isBareKeyChar(r): + return lexBareTableName + case r == tableSep || r == tableEnd: + lx.backup() + lx.emitTrim(itemText) + return lexTableNameEnd + default: + return lx.errorf("Bare keys cannot contain %q.", r) + } +} + +// lexTableNameEnd reads the end of a piece of a table name, optionally +// consuming whitespace. +func lexTableNameEnd(lx *lexer) stateFn { + switch r := lx.next(); { + case isWhitespace(r): + return lexTableNameEnd + case r == tableSep: + lx.ignore() + return lexTableNameStart + case r == tableEnd: + return lx.pop() + default: + return lx.errorf("Expected '.' or ']' to end table name, but got %q "+ + "instead.", r) + } +} + +// lexKeyStart consumes a key name up until the first non-whitespace character. +// lexKeyStart will ignore whitespace. +func lexKeyStart(lx *lexer) stateFn { + r := lx.peek() + switch { + case r == keySep: + return lx.errorf("Unexpected key separator %q.", keySep) + case isWhitespace(r) || isNL(r): + lx.next() + return lexSkip(lx, lexKeyStart) + case r == stringStart || r == rawStringStart: + lx.ignore() + lx.emit(itemKeyStart) + lx.push(lexKeyEnd) + return lexValue // reuse string lexing + default: + lx.ignore() + lx.emit(itemKeyStart) + return lexBareKey + } +} + +// lexBareKey consumes the text of a bare key. Assumes that the first character +// (which is not whitespace) has not yet been consumed. +func lexBareKey(lx *lexer) stateFn { + switch r := lx.next(); { + case isBareKeyChar(r): + return lexBareKey + case isWhitespace(r): + lx.emitTrim(itemText) + return lexKeyEnd + case r == keySep: + lx.backup() + lx.emitTrim(itemText) + return lexKeyEnd + default: + return lx.errorf("Bare keys cannot contain %q.", r) + } +} + +// lexKeyEnd consumes the end of a key and trims whitespace (up to the key +// separator). +func lexKeyEnd(lx *lexer) stateFn { + switch r := lx.next(); { + case r == keySep: + return lexSkip(lx, lexValue) + case isWhitespace(r): + return lexSkip(lx, lexKeyEnd) + default: + return lx.errorf("Expected key separator %q, but got %q instead.", + keySep, r) + } +} + +// lexValue starts the consumption of a value anywhere a value is expected. +// lexValue will ignore whitespace. +// After a value is lexed, the last state on the next is popped and returned. +func lexValue(lx *lexer) stateFn { + // We allow whitespace to precede a value, but NOT new lines. + // In array syntax, the array states are responsible for ignoring new + // lines. + r := lx.next() + if isWhitespace(r) { + return lexSkip(lx, lexValue) + } + + switch { + case r == arrayStart: + lx.ignore() + lx.emit(itemArray) + return lexArrayValue + case r == stringStart: + if lx.accept(stringStart) { + if lx.accept(stringStart) { + lx.ignore() // Ignore """ + return lexMultilineString + } + lx.backup() + } + lx.ignore() // ignore the '"' + return lexString + case r == rawStringStart: + if lx.accept(rawStringStart) { + if lx.accept(rawStringStart) { + lx.ignore() // Ignore """ + return lexMultilineRawString + } + lx.backup() + } + lx.ignore() // ignore the "'" + return lexRawString + case r == 't': + return lexTrue + case r == 'f': + return lexFalse + case r == '-': + return lexNumberStart + case isDigit(r): + lx.backup() // avoid an extra state and use the same as above + return lexNumberOrDateStart + case r == '.': // special error case, be kind to users + return lx.errorf("Floats must start with a digit, not '.'.") + } + return lx.errorf("Expected value but found %q instead.", r) +} + +// lexArrayValue consumes one value in an array. It assumes that '[' or ',' +// have already been consumed. All whitespace and new lines are ignored. +func lexArrayValue(lx *lexer) stateFn { + r := lx.next() + switch { + case isWhitespace(r) || isNL(r): + return lexSkip(lx, lexArrayValue) + case r == commentStart: + lx.push(lexArrayValue) + return lexCommentStart + case r == arrayValTerm: + return lx.errorf("Unexpected array value terminator %q.", + arrayValTerm) + case r == arrayEnd: + return lexArrayEnd + } + + lx.backup() + lx.push(lexArrayValueEnd) + return lexValue +} + +// lexArrayValueEnd consumes the cruft between values of an array. Namely, +// it ignores whitespace and expects either a ',' or a ']'. +func lexArrayValueEnd(lx *lexer) stateFn { + r := lx.next() + switch { + case isWhitespace(r) || isNL(r): + return lexSkip(lx, lexArrayValueEnd) + case r == commentStart: + lx.push(lexArrayValueEnd) + return lexCommentStart + case r == arrayValTerm: + lx.ignore() + return lexArrayValue // move on to the next value + case r == arrayEnd: + return lexArrayEnd + } + return lx.errorf("Expected an array value terminator %q or an array "+ + "terminator %q, but got %q instead.", arrayValTerm, arrayEnd, r) +} + +// lexArrayEnd finishes the lexing of an array. It assumes that a ']' has +// just been consumed. +func lexArrayEnd(lx *lexer) stateFn { + lx.ignore() + lx.emit(itemArrayEnd) + return lx.pop() +} + +// lexString consumes the inner contents of a string. It assumes that the +// beginning '"' has already been consumed and ignored. +func lexString(lx *lexer) stateFn { + r := lx.next() + switch { + case isNL(r): + return lx.errorf("Strings cannot contain new lines.") + case r == '\\': + lx.push(lexString) + return lexStringEscape + case r == stringEnd: + lx.backup() + lx.emit(itemString) + lx.next() + lx.ignore() + return lx.pop() + } + return lexString +} + +// lexMultilineString consumes the inner contents of a string. It assumes that +// the beginning '"""' has already been consumed and ignored. +func lexMultilineString(lx *lexer) stateFn { + r := lx.next() + switch { + case r == '\\': + return lexMultilineStringEscape + case r == stringEnd: + if lx.accept(stringEnd) { + if lx.accept(stringEnd) { + lx.backup() + lx.backup() + lx.backup() + lx.emit(itemMultilineString) + lx.next() + lx.next() + lx.next() + lx.ignore() + return lx.pop() + } + lx.backup() + } + } + return lexMultilineString +} + +// lexRawString consumes a raw string. Nothing can be escaped in such a string. +// It assumes that the beginning "'" has already been consumed and ignored. +func lexRawString(lx *lexer) stateFn { + r := lx.next() + switch { + case isNL(r): + return lx.errorf("Strings cannot contain new lines.") + case r == rawStringEnd: + lx.backup() + lx.emit(itemRawString) + lx.next() + lx.ignore() + return lx.pop() + } + return lexRawString +} + +// lexMultilineRawString consumes a raw string. Nothing can be escaped in such +// a string. It assumes that the beginning "'" has already been consumed and +// ignored. +func lexMultilineRawString(lx *lexer) stateFn { + r := lx.next() + switch { + case r == rawStringEnd: + if lx.accept(rawStringEnd) { + if lx.accept(rawStringEnd) { + lx.backup() + lx.backup() + lx.backup() + lx.emit(itemRawMultilineString) + lx.next() + lx.next() + lx.next() + lx.ignore() + return lx.pop() + } + lx.backup() + } + } + return lexMultilineRawString +} + +// lexMultilineStringEscape consumes an escaped character. It assumes that the +// preceding '\\' has already been consumed. +func lexMultilineStringEscape(lx *lexer) stateFn { + // Handle the special case first: + if isNL(lx.next()) { + lx.next() + return lexMultilineString + } else { + lx.backup() + lx.push(lexMultilineString) + return lexStringEscape(lx) + } +} + +func lexStringEscape(lx *lexer) stateFn { + r := lx.next() + switch r { + case 'b': + fallthrough + case 't': + fallthrough + case 'n': + fallthrough + case 'f': + fallthrough + case 'r': + fallthrough + case '"': + fallthrough + case '\\': + return lx.pop() + case 'u': + return lexShortUnicodeEscape + case 'U': + return lexLongUnicodeEscape + } + return lx.errorf("Invalid escape character %q. Only the following "+ + "escape characters are allowed: "+ + "\\b, \\t, \\n, \\f, \\r, \\\", \\/, \\\\, "+ + "\\uXXXX and \\UXXXXXXXX.", r) +} + +func lexShortUnicodeEscape(lx *lexer) stateFn { + var r rune + for i := 0; i < 4; i++ { + r = lx.next() + if !isHexadecimal(r) { + return lx.errorf("Expected four hexadecimal digits after '\\u', "+ + "but got '%s' instead.", lx.current()) + } + } + return lx.pop() +} + +func lexLongUnicodeEscape(lx *lexer) stateFn { + var r rune + for i := 0; i < 8; i++ { + r = lx.next() + if !isHexadecimal(r) { + return lx.errorf("Expected eight hexadecimal digits after '\\U', "+ + "but got '%s' instead.", lx.current()) + } + } + return lx.pop() +} + +// lexNumberOrDateStart consumes either a (positive) integer, float or +// datetime. It assumes that NO negative sign has been consumed. +func lexNumberOrDateStart(lx *lexer) stateFn { + r := lx.next() + if !isDigit(r) { + if r == '.' { + return lx.errorf("Floats must start with a digit, not '.'.") + } else { + return lx.errorf("Expected a digit but got %q.", r) + } + } + return lexNumberOrDate +} + +// lexNumberOrDate consumes either a (positive) integer, float or datetime. +func lexNumberOrDate(lx *lexer) stateFn { + r := lx.next() + switch { + case r == '-': + if lx.pos-lx.start != 5 { + return lx.errorf("All ISO8601 dates must be in full Zulu form.") + } + return lexDateAfterYear + case isDigit(r): + return lexNumberOrDate + case r == '.': + return lexFloatStart + } + + lx.backup() + lx.emit(itemInteger) + return lx.pop() +} + +// lexDateAfterYear consumes a full Zulu Datetime in ISO8601 format. +// It assumes that "YYYY-" has already been consumed. +func lexDateAfterYear(lx *lexer) stateFn { + formats := []rune{ + // digits are '0'. + // everything else is direct equality. + '0', '0', '-', '0', '0', + 'T', + '0', '0', ':', '0', '0', ':', '0', '0', + 'Z', + } + for _, f := range formats { + r := lx.next() + if f == '0' { + if !isDigit(r) { + return lx.errorf("Expected digit in ISO8601 datetime, "+ + "but found %q instead.", r) + } + } else if f != r { + return lx.errorf("Expected %q in ISO8601 datetime, "+ + "but found %q instead.", f, r) + } + } + lx.emit(itemDatetime) + return lx.pop() +} + +// lexNumberStart consumes either an integer or a float. It assumes that +// a negative sign has already been read, but that *no* digits have been +// consumed. lexNumberStart will move to the appropriate integer or float +// states. +func lexNumberStart(lx *lexer) stateFn { + // we MUST see a digit. Even floats have to start with a digit. + r := lx.next() + if !isDigit(r) { + if r == '.' { + return lx.errorf("Floats must start with a digit, not '.'.") + } else { + return lx.errorf("Expected a digit but got %q.", r) + } + } + return lexNumber +} + +// lexNumber consumes an integer or a float after seeing the first digit. +func lexNumber(lx *lexer) stateFn { + r := lx.next() + switch { + case isDigit(r): + return lexNumber + case r == '.': + return lexFloatStart + } + + lx.backup() + lx.emit(itemInteger) + return lx.pop() +} + +// lexFloatStart starts the consumption of digits of a float after a '.'. +// Namely, at least one digit is required. +func lexFloatStart(lx *lexer) stateFn { + r := lx.next() + if !isDigit(r) { + return lx.errorf("Floats must have a digit after the '.', but got "+ + "%q instead.", r) + } + return lexFloat +} + +// lexFloat consumes the digits of a float after a '.'. +// Assumes that one digit has been consumed after a '.' already. +func lexFloat(lx *lexer) stateFn { + r := lx.next() + if isDigit(r) { + return lexFloat + } + + lx.backup() + lx.emit(itemFloat) + return lx.pop() +} + +// lexConst consumes the s[1:] in s. It assumes that s[0] has already been +// consumed. +func lexConst(lx *lexer, s string) stateFn { + for i := range s[1:] { + if r := lx.next(); r != rune(s[i+1]) { + return lx.errorf("Expected %q, but found %q instead.", s[:i+1], + s[:i]+string(r)) + } + } + return nil +} + +// lexTrue consumes the "rue" in "true". It assumes that 't' has already +// been consumed. +func lexTrue(lx *lexer) stateFn { + if fn := lexConst(lx, "true"); fn != nil { + return fn + } + lx.emit(itemBool) + return lx.pop() +} + +// lexFalse consumes the "alse" in "false". It assumes that 'f' has already +// been consumed. +func lexFalse(lx *lexer) stateFn { + if fn := lexConst(lx, "false"); fn != nil { + return fn + } + lx.emit(itemBool) + return lx.pop() +} + +// lexCommentStart begins the lexing of a comment. It will emit +// itemCommentStart and consume no characters, passing control to lexComment. +func lexCommentStart(lx *lexer) stateFn { + lx.ignore() + lx.emit(itemCommentStart) + return lexComment +} + +// lexComment lexes an entire comment. It assumes that '#' has been consumed. +// It will consume *up to* the first new line character, and pass control +// back to the last state on the stack. +func lexComment(lx *lexer) stateFn { + r := lx.peek() + if isNL(r) || r == eof { + lx.emit(itemText) + return lx.pop() + } + lx.next() + return lexComment +} + +// lexSkip ignores all slurped input and moves on to the next state. +func lexSkip(lx *lexer, nextState stateFn) stateFn { + return func(lx *lexer) stateFn { + lx.ignore() + return nextState + } +} + +// isWhitespace returns true if `r` is a whitespace character according +// to the spec. +func isWhitespace(r rune) bool { + return r == '\t' || r == ' ' +} + +func isNL(r rune) bool { + return r == '\n' || r == '\r' +} + +func isDigit(r rune) bool { + return r >= '0' && r <= '9' +} + +func isHexadecimal(r rune) bool { + return (r >= '0' && r <= '9') || + (r >= 'a' && r <= 'f') || + (r >= 'A' && r <= 'F') +} + +func isBareKeyChar(r rune) bool { + return (r >= 'A' && r <= 'Z') || + (r >= 'a' && r <= 'z') || + (r >= '0' && r <= '9') || + r == '_' || + r == '-' +} + +func (itype itemType) String() string { + switch itype { + case itemError: + return "Error" + case itemNIL: + return "NIL" + case itemEOF: + return "EOF" + case itemText: + return "Text" + case itemString: + return "String" + case itemRawString: + return "String" + case itemMultilineString: + return "String" + case itemRawMultilineString: + return "String" + case itemBool: + return "Bool" + case itemInteger: + return "Integer" + case itemFloat: + return "Float" + case itemDatetime: + return "DateTime" + case itemTableStart: + return "TableStart" + case itemTableEnd: + return "TableEnd" + case itemKeyStart: + return "KeyStart" + case itemArray: + return "Array" + case itemArrayEnd: + return "ArrayEnd" + case itemCommentStart: + return "CommentStart" + } + panic(fmt.Sprintf("BUG: Unknown type '%d'.", int(itype))) +} + +func (item item) String() string { + return fmt.Sprintf("(%s, %s)", item.typ.String(), item.val) +} diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/parse.go b/Godeps/_workspace/src/github.com/BurntSushi/toml/parse.go new file mode 100644 index 00000000..c6069be1 --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/parse.go @@ -0,0 +1,498 @@ +package toml + +import ( + "fmt" + "log" + "strconv" + "strings" + "time" + "unicode" + "unicode/utf8" +) + +type parser struct { + mapping map[string]interface{} + types map[string]tomlType + lx *lexer + + // A list of keys in the order that they appear in the TOML data. + ordered []Key + + // the full key for the current hash in scope + context Key + + // the base key name for everything except hashes + currentKey string + + // rough approximation of line number + approxLine int + + // A map of 'key.group.names' to whether they were created implicitly. + implicits map[string]bool +} + +type parseError string + +func (pe parseError) Error() string { + return string(pe) +} + +func parse(data string) (p *parser, err error) { + defer func() { + if r := recover(); r != nil { + var ok bool + if err, ok = r.(parseError); ok { + return + } + panic(r) + } + }() + + p = &parser{ + mapping: make(map[string]interface{}), + types: make(map[string]tomlType), + lx: lex(data), + ordered: make([]Key, 0), + implicits: make(map[string]bool), + } + for { + item := p.next() + if item.typ == itemEOF { + break + } + p.topLevel(item) + } + + return p, nil +} + +func (p *parser) panicf(format string, v ...interface{}) { + msg := fmt.Sprintf("Near line %d (last key parsed '%s'): %s", + p.approxLine, p.current(), fmt.Sprintf(format, v...)) + panic(parseError(msg)) +} + +func (p *parser) next() item { + it := p.lx.nextItem() + if it.typ == itemError { + p.panicf("%s", it.val) + } + return it +} + +func (p *parser) bug(format string, v ...interface{}) { + log.Fatalf("BUG: %s\n\n", fmt.Sprintf(format, v...)) +} + +func (p *parser) expect(typ itemType) item { + it := p.next() + p.assertEqual(typ, it.typ) + return it +} + +func (p *parser) assertEqual(expected, got itemType) { + if expected != got { + p.bug("Expected '%s' but got '%s'.", expected, got) + } +} + +func (p *parser) topLevel(item item) { + switch item.typ { + case itemCommentStart: + p.approxLine = item.line + p.expect(itemText) + case itemTableStart: + kg := p.next() + p.approxLine = kg.line + + var key Key + for ; kg.typ != itemTableEnd && kg.typ != itemEOF; kg = p.next() { + key = append(key, p.keyString(kg)) + } + p.assertEqual(itemTableEnd, kg.typ) + + p.establishContext(key, false) + p.setType("", tomlHash) + p.ordered = append(p.ordered, key) + case itemArrayTableStart: + kg := p.next() + p.approxLine = kg.line + + var key Key + for ; kg.typ != itemArrayTableEnd && kg.typ != itemEOF; kg = p.next() { + key = append(key, p.keyString(kg)) + } + p.assertEqual(itemArrayTableEnd, kg.typ) + + p.establishContext(key, true) + p.setType("", tomlArrayHash) + p.ordered = append(p.ordered, key) + case itemKeyStart: + kname := p.next() + p.approxLine = kname.line + p.currentKey = p.keyString(kname) + + val, typ := p.value(p.next()) + p.setValue(p.currentKey, val) + p.setType(p.currentKey, typ) + p.ordered = append(p.ordered, p.context.add(p.currentKey)) + p.currentKey = "" + default: + p.bug("Unexpected type at top level: %s", item.typ) + } +} + +// Gets a string for a key (or part of a key in a table name). +func (p *parser) keyString(it item) string { + switch it.typ { + case itemText: + return it.val + case itemString, itemMultilineString, + itemRawString, itemRawMultilineString: + s, _ := p.value(it) + return s.(string) + default: + p.bug("Unexpected key type: %s", it.typ) + panic("unreachable") + } +} + +// value translates an expected value from the lexer into a Go value wrapped +// as an empty interface. +func (p *parser) value(it item) (interface{}, tomlType) { + switch it.typ { + case itemString: + return p.replaceEscapes(it.val), p.typeOfPrimitive(it) + case itemMultilineString: + trimmed := stripFirstNewline(stripEscapedWhitespace(it.val)) + return p.replaceEscapes(trimmed), p.typeOfPrimitive(it) + case itemRawString: + return it.val, p.typeOfPrimitive(it) + case itemRawMultilineString: + return stripFirstNewline(it.val), p.typeOfPrimitive(it) + case itemBool: + switch it.val { + case "true": + return true, p.typeOfPrimitive(it) + case "false": + return false, p.typeOfPrimitive(it) + } + p.bug("Expected boolean value, but got '%s'.", it.val) + case itemInteger: + num, err := strconv.ParseInt(it.val, 10, 64) + if err != nil { + // See comment below for floats describing why we make a + // distinction between a bug and a user error. + if e, ok := err.(*strconv.NumError); ok && + e.Err == strconv.ErrRange { + + p.panicf("Integer '%s' is out of the range of 64-bit "+ + "signed integers.", it.val) + } else { + p.bug("Expected integer value, but got '%s'.", it.val) + } + } + return num, p.typeOfPrimitive(it) + case itemFloat: + num, err := strconv.ParseFloat(it.val, 64) + if err != nil { + // Distinguish float values. Normally, it'd be a bug if the lexer + // provides an invalid float, but it's possible that the float is + // out of range of valid values (which the lexer cannot determine). + // So mark the former as a bug but the latter as a legitimate user + // error. + // + // This is also true for integers. + if e, ok := err.(*strconv.NumError); ok && + e.Err == strconv.ErrRange { + + p.panicf("Float '%s' is out of the range of 64-bit "+ + "IEEE-754 floating-point numbers.", it.val) + } else { + p.bug("Expected float value, but got '%s'.", it.val) + } + } + return num, p.typeOfPrimitive(it) + case itemDatetime: + t, err := time.Parse("2006-01-02T15:04:05Z", it.val) + if err != nil { + p.bug("Expected Zulu formatted DateTime, but got '%s'.", it.val) + } + return t, p.typeOfPrimitive(it) + case itemArray: + array := make([]interface{}, 0) + types := make([]tomlType, 0) + + for it = p.next(); it.typ != itemArrayEnd; it = p.next() { + if it.typ == itemCommentStart { + p.expect(itemText) + continue + } + + val, typ := p.value(it) + array = append(array, val) + types = append(types, typ) + } + return array, p.typeOfArray(types) + } + p.bug("Unexpected value type: %s", it.typ) + panic("unreachable") +} + +// establishContext sets the current context of the parser, +// where the context is either a hash or an array of hashes. Which one is +// set depends on the value of the `array` parameter. +// +// Establishing the context also makes sure that the key isn't a duplicate, and +// will create implicit hashes automatically. +func (p *parser) establishContext(key Key, array bool) { + var ok bool + + // Always start at the top level and drill down for our context. + hashContext := p.mapping + keyContext := make(Key, 0) + + // We only need implicit hashes for key[0:-1] + for _, k := range key[0 : len(key)-1] { + _, ok = hashContext[k] + keyContext = append(keyContext, k) + + // No key? Make an implicit hash and move on. + if !ok { + p.addImplicit(keyContext) + hashContext[k] = make(map[string]interface{}) + } + + // If the hash context is actually an array of tables, then set + // the hash context to the last element in that array. + // + // Otherwise, it better be a table, since this MUST be a key group (by + // virtue of it not being the last element in a key). + switch t := hashContext[k].(type) { + case []map[string]interface{}: + hashContext = t[len(t)-1] + case map[string]interface{}: + hashContext = t + default: + p.panicf("Key '%s' was already created as a hash.", keyContext) + } + } + + p.context = keyContext + if array { + // If this is the first element for this array, then allocate a new + // list of tables for it. + k := key[len(key)-1] + if _, ok := hashContext[k]; !ok { + hashContext[k] = make([]map[string]interface{}, 0, 5) + } + + // Add a new table. But make sure the key hasn't already been used + // for something else. + if hash, ok := hashContext[k].([]map[string]interface{}); ok { + hashContext[k] = append(hash, make(map[string]interface{})) + } else { + p.panicf("Key '%s' was already created and cannot be used as "+ + "an array.", keyContext) + } + } else { + p.setValue(key[len(key)-1], make(map[string]interface{})) + } + p.context = append(p.context, key[len(key)-1]) +} + +// setValue sets the given key to the given value in the current context. +// It will make sure that the key hasn't already been defined, account for +// implicit key groups. +func (p *parser) setValue(key string, value interface{}) { + var tmpHash interface{} + var ok bool + + hash := p.mapping + keyContext := make(Key, 0) + for _, k := range p.context { + keyContext = append(keyContext, k) + if tmpHash, ok = hash[k]; !ok { + p.bug("Context for key '%s' has not been established.", keyContext) + } + switch t := tmpHash.(type) { + case []map[string]interface{}: + // The context is a table of hashes. Pick the most recent table + // defined as the current hash. + hash = t[len(t)-1] + case map[string]interface{}: + hash = t + default: + p.bug("Expected hash to have type 'map[string]interface{}', but "+ + "it has '%T' instead.", tmpHash) + } + } + keyContext = append(keyContext, key) + + if _, ok := hash[key]; ok { + // Typically, if the given key has already been set, then we have + // to raise an error since duplicate keys are disallowed. However, + // it's possible that a key was previously defined implicitly. In this + // case, it is allowed to be redefined concretely. (See the + // `tests/valid/implicit-and-explicit-after.toml` test in `toml-test`.) + // + // But we have to make sure to stop marking it as an implicit. (So that + // another redefinition provokes an error.) + // + // Note that since it has already been defined (as a hash), we don't + // want to overwrite it. So our business is done. + if p.isImplicit(keyContext) { + p.removeImplicit(keyContext) + return + } + + // Otherwise, we have a concrete key trying to override a previous + // key, which is *always* wrong. + p.panicf("Key '%s' has already been defined.", keyContext) + } + hash[key] = value +} + +// setType sets the type of a particular value at a given key. +// It should be called immediately AFTER setValue. +// +// Note that if `key` is empty, then the type given will be applied to the +// current context (which is either a table or an array of tables). +func (p *parser) setType(key string, typ tomlType) { + keyContext := make(Key, 0, len(p.context)+1) + for _, k := range p.context { + keyContext = append(keyContext, k) + } + if len(key) > 0 { // allow type setting for hashes + keyContext = append(keyContext, key) + } + p.types[keyContext.String()] = typ +} + +// addImplicit sets the given Key as having been created implicitly. +func (p *parser) addImplicit(key Key) { + p.implicits[key.String()] = true +} + +// removeImplicit stops tagging the given key as having been implicitly +// created. +func (p *parser) removeImplicit(key Key) { + p.implicits[key.String()] = false +} + +// isImplicit returns true if the key group pointed to by the key was created +// implicitly. +func (p *parser) isImplicit(key Key) bool { + return p.implicits[key.String()] +} + +// current returns the full key name of the current context. +func (p *parser) current() string { + if len(p.currentKey) == 0 { + return p.context.String() + } + if len(p.context) == 0 { + return p.currentKey + } + return fmt.Sprintf("%s.%s", p.context, p.currentKey) +} + +func stripFirstNewline(s string) string { + if len(s) == 0 || s[0] != '\n' { + return s + } + return s[1:len(s)] +} + +func stripEscapedWhitespace(s string) string { + esc := strings.Split(s, "\\\n") + if len(esc) > 1 { + for i := 1; i < len(esc); i++ { + esc[i] = strings.TrimLeftFunc(esc[i], unicode.IsSpace) + } + } + return strings.Join(esc, "") +} + +func (p *parser) replaceEscapes(str string) string { + var replaced []rune + s := []byte(str) + r := 0 + for r < len(s) { + if s[r] != '\\' { + c, size := utf8.DecodeRune(s[r:]) + r += size + replaced = append(replaced, c) + continue + } + r += 1 + if r >= len(s) { + p.bug("Escape sequence at end of string.") + return "" + } + switch s[r] { + default: + p.bug("Expected valid escape code after \\, but got %q.", s[r]) + return "" + case 'b': + replaced = append(replaced, rune(0x0008)) + r += 1 + case 't': + replaced = append(replaced, rune(0x0009)) + r += 1 + case 'n': + replaced = append(replaced, rune(0x000A)) + r += 1 + case 'f': + replaced = append(replaced, rune(0x000C)) + r += 1 + case 'r': + replaced = append(replaced, rune(0x000D)) + r += 1 + case '"': + replaced = append(replaced, rune(0x0022)) + r += 1 + case '\\': + replaced = append(replaced, rune(0x005C)) + r += 1 + case 'u': + // At this point, we know we have a Unicode escape of the form + // `uXXXX` at [r, r+5). (Because the lexer guarantees this + // for us.) + escaped := p.asciiEscapeToUnicode(s[r+1 : r+5]) + replaced = append(replaced, escaped) + r += 5 + case 'U': + // At this point, we know we have a Unicode escape of the form + // `uXXXX` at [r, r+9). (Because the lexer guarantees this + // for us.) + escaped := p.asciiEscapeToUnicode(s[r+1 : r+9]) + replaced = append(replaced, escaped) + r += 9 + } + } + return string(replaced) +} + +func (p *parser) asciiEscapeToUnicode(bs []byte) rune { + s := string(bs) + hex, err := strconv.ParseUint(strings.ToLower(s), 16, 32) + if err != nil { + p.bug("Could not parse '%s' as a hexadecimal number, but the "+ + "lexer claims it's OK: %s", s, err) + } + + // BUG(burntsushi) + // I honestly don't understand how this works. I can't seem + // to find a way to make this fail. I figured this would fail on invalid + // UTF-8 characters like U+DCFF, but it doesn't. + if !utf8.ValidString(string(rune(hex))) { + p.panicf("Escaped character '\\u%s' is not valid UTF-8.", s) + } + return rune(hex) +} + +func isStringType(ty itemType) bool { + return ty == itemString || ty == itemMultilineString || + ty == itemRawString || ty == itemRawMultilineString +} diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/session.vim b/Godeps/_workspace/src/github.com/BurntSushi/toml/session.vim new file mode 100644 index 00000000..562164be --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/session.vim @@ -0,0 +1 @@ +au BufWritePost *.go silent!make tags > /dev/null 2>&1 diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/type_check.go b/Godeps/_workspace/src/github.com/BurntSushi/toml/type_check.go new file mode 100644 index 00000000..c73f8afc --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/type_check.go @@ -0,0 +1,91 @@ +package toml + +// tomlType represents any Go type that corresponds to a TOML type. +// While the first draft of the TOML spec has a simplistic type system that +// probably doesn't need this level of sophistication, we seem to be militating +// toward adding real composite types. +type tomlType interface { + typeString() string +} + +// typeEqual accepts any two types and returns true if they are equal. +func typeEqual(t1, t2 tomlType) bool { + if t1 == nil || t2 == nil { + return false + } + return t1.typeString() == t2.typeString() +} + +func typeIsHash(t tomlType) bool { + return typeEqual(t, tomlHash) || typeEqual(t, tomlArrayHash) +} + +type tomlBaseType string + +func (btype tomlBaseType) typeString() string { + return string(btype) +} + +func (btype tomlBaseType) String() string { + return btype.typeString() +} + +var ( + tomlInteger tomlBaseType = "Integer" + tomlFloat tomlBaseType = "Float" + tomlDatetime tomlBaseType = "Datetime" + tomlString tomlBaseType = "String" + tomlBool tomlBaseType = "Bool" + tomlArray tomlBaseType = "Array" + tomlHash tomlBaseType = "Hash" + tomlArrayHash tomlBaseType = "ArrayHash" +) + +// typeOfPrimitive returns a tomlType of any primitive value in TOML. +// Primitive values are: Integer, Float, Datetime, String and Bool. +// +// Passing a lexer item other than the following will cause a BUG message +// to occur: itemString, itemBool, itemInteger, itemFloat, itemDatetime. +func (p *parser) typeOfPrimitive(lexItem item) tomlType { + switch lexItem.typ { + case itemInteger: + return tomlInteger + case itemFloat: + return tomlFloat + case itemDatetime: + return tomlDatetime + case itemString: + return tomlString + case itemMultilineString: + return tomlString + case itemRawString: + return tomlString + case itemRawMultilineString: + return tomlString + case itemBool: + return tomlBool + } + p.bug("Cannot infer primitive type of lex item '%s'.", lexItem) + panic("unreachable") +} + +// typeOfArray returns a tomlType for an array given a list of types of its +// values. +// +// In the current spec, if an array is homogeneous, then its type is always +// "Array". If the array is not homogeneous, an error is generated. +func (p *parser) typeOfArray(types []tomlType) tomlType { + // Empty arrays are cool. + if len(types) == 0 { + return tomlArray + } + + theType := types[0] + for _, t := range types[1:] { + if !typeEqual(theType, t) { + p.panicf("Array contains values of type '%s' and '%s', but "+ + "arrays must be homogeneous.", theType, t) + } + } + return tomlArray +} diff --git a/Godeps/_workspace/src/github.com/BurntSushi/toml/type_fields.go b/Godeps/_workspace/src/github.com/BurntSushi/toml/type_fields.go new file mode 100644 index 00000000..7592f87a --- /dev/null +++ b/Godeps/_workspace/src/github.com/BurntSushi/toml/type_fields.go @@ -0,0 +1,241 @@ +package toml + +// Struct field handling is adapted from code in encoding/json: +// +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the Go distribution. + +import ( + "reflect" + "sort" + "sync" +) + +// A field represents a single field found in a struct. +type field struct { + name string // the name of the field (`toml` tag included) + tag bool // whether field has a `toml` tag + index []int // represents the depth of an anonymous field + typ reflect.Type // the type of the field +} + +// byName sorts field by name, breaking ties with depth, +// then breaking ties with "name came from toml tag", then +// breaking ties with index sequence. +type byName []field + +func (x byName) Len() int { return len(x) } + +func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] } + +func (x byName) Less(i, j int) bool { + if x[i].name != x[j].name { + return x[i].name < x[j].name + } + if len(x[i].index) != len(x[j].index) { + return len(x[i].index) < len(x[j].index) + } + if x[i].tag != x[j].tag { + return x[i].tag + } + return byIndex(x).Less(i, j) +} + +// byIndex sorts field by index sequence. +type byIndex []field + +func (x byIndex) Len() int { return len(x) } + +func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] } + +func (x byIndex) Less(i, j int) bool { + for k, xik := range x[i].index { + if k >= len(x[j].index) { + return false + } + if xik != x[j].index[k] { + return xik < x[j].index[k] + } + } + return len(x[i].index) < len(x[j].index) +} + +// typeFields returns a list of fields that TOML should recognize for the given +// type. The algorithm is breadth-first search over the set of structs to +// include - the top struct and then any reachable anonymous structs. +func typeFields(t reflect.Type) []field { + // Anonymous fields to explore at the current level and the next. + current := []field{} + next := []field{{typ: t}} + + // Count of queued names for current level and the next. + count := map[reflect.Type]int{} + nextCount := map[reflect.Type]int{} + + // Types already visited at an earlier level. + visited := map[reflect.Type]bool{} + + // Fields found. + var fields []field + + for len(next) > 0 { + current, next = next, current[:0] + count, nextCount = nextCount, map[reflect.Type]int{} + + for _, f := range current { + if visited[f.typ] { + continue + } + visited[f.typ] = true + + // Scan f.typ for fields to include. + for i := 0; i < f.typ.NumField(); i++ { + sf := f.typ.Field(i) + if sf.PkgPath != "" { // unexported + continue + } + name := sf.Tag.Get("toml") + if name == "-" { + continue + } + index := make([]int, len(f.index)+1) + copy(index, f.index) + index[len(f.index)] = i + + ft := sf.Type + if ft.Name() == "" && ft.Kind() == reflect.Ptr { + // Follow pointer. + ft = ft.Elem() + } + + // Record found field and index sequence. + if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct { + tagged := name != "" + if name == "" { + name = sf.Name + } + fields = append(fields, field{name, tagged, index, ft}) + if count[f.typ] > 1 { + // If there were multiple instances, add a second, + // so that the annihilation code will see a duplicate. + // It only cares about the distinction between 1 or 2, + // so don't bother generating any more copies. + fields = append(fields, fields[len(fields)-1]) + } + continue + } + + // Record new anonymous struct to explore in next round. + nextCount[ft]++ + if nextCount[ft] == 1 { + f := field{name: ft.Name(), index: index, typ: ft} + next = append(next, f) + } + } + } + } + + sort.Sort(byName(fields)) + + // Delete all fields that are hidden by the Go rules for embedded fields, + // except that fields with TOML tags are promoted. + + // The fields are sorted in primary order of name, secondary order + // of field index length. Loop over names; for each name, delete + // hidden fields by choosing the one dominant field that survives. + out := fields[:0] + for advance, i := 0, 0; i < len(fields); i += advance { + // One iteration per name. + // Find the sequence of fields with the name of this first field. + fi := fields[i] + name := fi.name + for advance = 1; i+advance < len(fields); advance++ { + fj := fields[i+advance] + if fj.name != name { + break + } + } + if advance == 1 { // Only one field with this name + out = append(out, fi) + continue + } + dominant, ok := dominantField(fields[i : i+advance]) + if ok { + out = append(out, dominant) + } + } + + fields = out + sort.Sort(byIndex(fields)) + + return fields +} + +// dominantField looks through the fields, all of which are known to +// have the same name, to find the single field that dominates the +// others using Go's embedding rules, modified by the presence of +// TOML tags. If there are multiple top-level fields, the boolean +// will be false: This condition is an error in Go and we skip all +// the fields. +func dominantField(fields []field) (field, bool) { + // The fields are sorted in increasing index-length order. The winner + // must therefore be one with the shortest index length. Drop all + // longer entries, which is easy: just truncate the slice. + length := len(fields[0].index) + tagged := -1 // Index of first tagged field. + for i, f := range fields { + if len(f.index) > length { + fields = fields[:i] + break + } + if f.tag { + if tagged >= 0 { + // Multiple tagged fields at the same level: conflict. + // Return no field. + return field{}, false + } + tagged = i + } + } + if tagged >= 0 { + return fields[tagged], true + } + // All remaining fields have the same length. If there's more than one, + // we have a conflict (two fields named "X" at the same level) and we + // return no field. + if len(fields) > 1 { + return field{}, false + } + return fields[0], true +} + +var fieldCache struct { + sync.RWMutex + m map[reflect.Type][]field +} + +// cachedTypeFields is like typeFields but uses a cache to avoid repeated work. +func cachedTypeFields(t reflect.Type) []field { + fieldCache.RLock() + f := fieldCache.m[t] + fieldCache.RUnlock() + if f != nil { + return f + } + + // Compute fields without lock. + // Might duplicate effort but won't hold other computations back. + f = typeFields(t) + if f == nil { + f = []field{} + } + + fieldCache.Lock() + if fieldCache.m == nil { + fieldCache.m = map[reflect.Type][]field{} + } + fieldCache.m[t] = f + fieldCache.Unlock() + return f +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/.gitignore b/Godeps/_workspace/src/github.com/armon/consul-api/.gitignore new file mode 100644 index 00000000..83656241 --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/.gitignore @@ -0,0 +1,23 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/LICENSE b/Godeps/_workspace/src/github.com/armon/consul-api/LICENSE new file mode 100644 index 00000000..f0e5c79e --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/LICENSE @@ -0,0 +1,362 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. "Contributor" + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. "Contributor Version" + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the terms of + a Secondary License. + +1.6. "Executable Form" + + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + + means a work that combines Covered Software with other material, in a + separate file or files, that is not Covered Software. + +1.8. "License" + + means this document. + +1.9. "Licensable" + + means having the right to grant, to the maximum extent possible, whether + at the time of the initial grant or subsequently, any and all of the + rights conveyed by this License. + +1.10. "Modifications" + + means any of the following: + + a. any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. "Patent Claims" of a Contributor + + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the License, + by the making, using, selling, offering for sale, having made, import, + or transfer of either its Contributions or its Contributor Version. + +1.12. "Secondary License" + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. "Source Code Form" + + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, "control" means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution + become effective for each Contribution on the date the Contributor first + distributes such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under + this License. No additional rights or licenses will be implied from the + distribution or licensing of Covered Software under this License. + Notwithstanding Section 2.1(b) above, no patent license is granted by a + Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of + its Contributions. + + This License does not grant any rights in the trademarks, service marks, + or logos of any Contributor (except as may be necessary to comply with + the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this + License (see Section 10.2) or under the terms of a Secondary License (if + permitted under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its + Contributions are its original creation(s) or it has sufficient rights to + grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under + applicable copyright doctrines of fair use, fair dealing, or other + equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under + the terms of this License. You must inform recipients that the Source + Code Form of the Covered Software is governed by the terms of this + License, and how they can obtain a copy of this License. You may not + attempt to alter or restrict the recipients' rights in the Source Code + Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter the + recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for + the Covered Software. If the Larger Work is a combination of Covered + Software with a work governed by one or more Secondary Licenses, and the + Covered Software is not Incompatible With Secondary Licenses, this + License permits You to additionally distribute such Covered Software + under the terms of such Secondary License(s), so that the recipient of + the Larger Work may, at their option, further distribute the Covered + Software under the terms of either this License or such Secondary + License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices + (including copyright notices, patent notices, disclaimers of warranty, or + limitations of liability) contained within the Source Code Form of the + Covered Software, except that You may alter any license notices to the + extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on + behalf of any Contributor. You must make it absolutely clear that any + such warranty, support, indemnity, or liability obligation is offered by + You alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, + judicial order, or regulation then You must: (a) comply with the terms of + this License to the maximum extent possible; and (b) describe the + limitations and the code they affect. Such description must be placed in a + text file included with all distributions of the Covered Software under + this License. Except to the extent prohibited by statute or regulation, + such description must be sufficiently detailed for a recipient of ordinary + skill to be able to understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing + basis, if such Contributor fails to notify You of the non-compliance by + some reasonable means prior to 60 days after You have come back into + compliance. Moreover, Your grants from a particular Contributor are + reinstated on an ongoing basis if such Contributor notifies You of the + non-compliance by some reasonable means, this is the first time You have + received notice of non-compliance with this License from such + Contributor, and You become compliant prior to 30 days after Your receipt + of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, + counter-claims, and cross-claims) alleging that a Contributor Version + directly or indirectly infringes any patent, then the rights granted to + You by any and all Contributors for the Covered Software under Section + 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an "as is" basis, + without warranty of any kind, either expressed, implied, or statutory, + including, without limitation, warranties that the Covered Software is free + of defects, merchantable, fit for a particular purpose or non-infringing. + The entire risk as to the quality and performance of the Covered Software + is with You. Should any Covered Software prove defective in any respect, + You (not any Contributor) assume the cost of any necessary servicing, + repair, or correction. This disclaimer of warranty constitutes an essential + part of this License. No use of any Covered Software is authorized under + this License except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from + such party's negligence to the extent applicable law prohibits such + limitation. Some jurisdictions do not allow the exclusion or limitation of + incidental or consequential damages, so this exclusion and limitation may + not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts + of a jurisdiction where the defendant maintains its principal place of + business and such litigation shall be governed by laws of that + jurisdiction, without reference to its conflict-of-law provisions. Nothing + in this Section shall prevent a party's ability to bring cross-claims or + counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. Any law or regulation which provides that + the language of a contract shall be construed against the drafter shall not + be used to construe this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version + of the License under which You originally received the Covered Software, + or under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a + modified version of this License if you rename the license and remove + any references to the name of the license steward (except to note that + such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses If You choose to distribute Source Code Form that is + Incompatible With Secondary Licenses under the terms of this version of + the License, the notice described in Exhibit B of this License must be + attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, +then You may include the notice in a location (such as a LICENSE file in a +relevant directory) where a recipient would be likely to look for such a +notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice + + This Source Code Form is "Incompatible + With Secondary Licenses", as defined by + the Mozilla Public License, v. 2.0. \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/README.md b/Godeps/_workspace/src/github.com/armon/consul-api/README.md new file mode 100644 index 00000000..c95d9dee --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/README.md @@ -0,0 +1,42 @@ +consul-api +========== + +*DEPRECATED* Please use [consul api package](https://github.com/hashicorp/consul/tree/master/api) instead. +Godocs for that package [are here](http://godoc.org/github.com/hashicorp/consul/api). + +This package provides the `consulapi` package which attempts to +provide programmatic access to the full Consul API. + +Currently, all of the Consul APIs included in version 0.4 are supported. + +Documentation +============= + +The full documentation is available on [Godoc](http://godoc.org/github.com/armon/consul-api) + +Usage +===== + +Below is an example of using the Consul client: + +```go +// Get a new client, with KV endpoints +client, _ := consulapi.NewClient(consulapi.DefaultConfig()) +kv := client.KV() + +// PUT a new KV pair +p := &consulapi.KVPair{Key: "foo", Value: []byte("test")} +_, err := kv.Put(p, nil) +if err != nil { + panic(err) +} + +// Lookup the pair +pair, _, err := kv.Get("foo", nil) +if err != nil { + panic(err) +} +fmt.Printf("KV: %v", pair) + +``` + diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/acl.go b/Godeps/_workspace/src/github.com/armon/consul-api/acl.go new file mode 100644 index 00000000..e0179f54 --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/acl.go @@ -0,0 +1,140 @@ +package consulapi + +const ( + // ACLCLientType is the client type token + ACLClientType = "client" + + // ACLManagementType is the management type token + ACLManagementType = "management" +) + +// ACLEntry is used to represent an ACL entry +type ACLEntry struct { + CreateIndex uint64 + ModifyIndex uint64 + ID string + Name string + Type string + Rules string +} + +// ACL can be used to query the ACL endpoints +type ACL struct { + c *Client +} + +// ACL returns a handle to the ACL endpoints +func (c *Client) ACL() *ACL { + return &ACL{c} +} + +// Create is used to generate a new token with the given parameters +func (a *ACL) Create(acl *ACLEntry, q *WriteOptions) (string, *WriteMeta, error) { + r := a.c.newRequest("PUT", "/v1/acl/create") + r.setWriteOptions(q) + r.obj = acl + rtt, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return "", nil, err + } + defer resp.Body.Close() + + wm := &WriteMeta{RequestTime: rtt} + var out struct{ ID string } + if err := decodeBody(resp, &out); err != nil { + return "", nil, err + } + return out.ID, wm, nil +} + +// Update is used to update the rules of an existing token +func (a *ACL) Update(acl *ACLEntry, q *WriteOptions) (*WriteMeta, error) { + r := a.c.newRequest("PUT", "/v1/acl/update") + r.setWriteOptions(q) + r.obj = acl + rtt, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + wm := &WriteMeta{RequestTime: rtt} + return wm, nil +} + +// Destroy is used to destroy a given ACL token ID +func (a *ACL) Destroy(id string, q *WriteOptions) (*WriteMeta, error) { + r := a.c.newRequest("PUT", "/v1/acl/destroy/"+id) + r.setWriteOptions(q) + rtt, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return nil, err + } + resp.Body.Close() + + wm := &WriteMeta{RequestTime: rtt} + return wm, nil +} + +// Clone is used to return a new token cloned from an existing one +func (a *ACL) Clone(id string, q *WriteOptions) (string, *WriteMeta, error) { + r := a.c.newRequest("PUT", "/v1/acl/clone/"+id) + r.setWriteOptions(q) + rtt, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return "", nil, err + } + defer resp.Body.Close() + + wm := &WriteMeta{RequestTime: rtt} + var out struct{ ID string } + if err := decodeBody(resp, &out); err != nil { + return "", nil, err + } + return out.ID, wm, nil +} + +// Info is used to query for information about an ACL token +func (a *ACL) Info(id string, q *QueryOptions) (*ACLEntry, *QueryMeta, error) { + r := a.c.newRequest("GET", "/v1/acl/info/"+id) + r.setQueryOptions(q) + rtt, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var entries []*ACLEntry + if err := decodeBody(resp, &entries); err != nil { + return nil, nil, err + } + if len(entries) > 0 { + return entries[0], qm, nil + } + return nil, qm, nil +} + +// List is used to get all the ACL tokens +func (a *ACL) List(q *QueryOptions) ([]*ACLEntry, *QueryMeta, error) { + r := a.c.newRequest("GET", "/v1/acl/list") + r.setQueryOptions(q) + rtt, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var entries []*ACLEntry + if err := decodeBody(resp, &entries); err != nil { + return nil, nil, err + } + return entries, qm, nil +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/acl_test.go b/Godeps/_workspace/src/github.com/armon/consul-api/acl_test.go new file mode 100644 index 00000000..7932c590 --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/acl_test.go @@ -0,0 +1,140 @@ +package consulapi + +import ( + "os" + "testing" +) + +// ROOT is a management token for the tests +var CONSUL_ROOT string + +func init() { + CONSUL_ROOT = os.Getenv("CONSUL_ROOT") +} + +func TestACL_CreateDestroy(t *testing.T) { + if CONSUL_ROOT == "" { + t.SkipNow() + } + c := makeClient(t) + c.config.Token = CONSUL_ROOT + acl := c.ACL() + + ae := ACLEntry{ + Name: "API test", + Type: ACLClientType, + Rules: `key "" { policy = "deny" }`, + } + + id, wm, err := acl.Create(&ae, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if wm.RequestTime == 0 { + t.Fatalf("bad: %v", wm) + } + + if id == "" { + t.Fatalf("invalid: %v", id) + } + + ae2, _, err := acl.Info(id, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if ae2.Name != ae.Name || ae2.Type != ae.Type || ae2.Rules != ae.Rules { + t.Fatalf("Bad: %#v", ae2) + } + + wm, err = acl.Destroy(id, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if wm.RequestTime == 0 { + t.Fatalf("bad: %v", wm) + } +} + +func TestACL_CloneDestroy(t *testing.T) { + if CONSUL_ROOT == "" { + t.SkipNow() + } + c := makeClient(t) + c.config.Token = CONSUL_ROOT + acl := c.ACL() + + id, wm, err := acl.Clone(CONSUL_ROOT, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if wm.RequestTime == 0 { + t.Fatalf("bad: %v", wm) + } + + if id == "" { + t.Fatalf("invalid: %v", id) + } + + wm, err = acl.Destroy(id, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if wm.RequestTime == 0 { + t.Fatalf("bad: %v", wm) + } +} + +func TestACL_Info(t *testing.T) { + if CONSUL_ROOT == "" { + t.SkipNow() + } + c := makeClient(t) + c.config.Token = CONSUL_ROOT + acl := c.ACL() + + ae, qm, err := acl.Info(CONSUL_ROOT, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if qm.LastIndex == 0 { + t.Fatalf("bad: %v", qm) + } + if !qm.KnownLeader { + t.Fatalf("bad: %v", qm) + } + + if ae == nil || ae.ID != CONSUL_ROOT || ae.Type != ACLManagementType { + t.Fatalf("bad: %#v", ae) + } +} + +func TestACL_List(t *testing.T) { + if CONSUL_ROOT == "" { + t.SkipNow() + } + c := makeClient(t) + c.config.Token = CONSUL_ROOT + acl := c.ACL() + + acls, qm, err := acl.List(nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(acls) < 2 { + t.Fatalf("bad: %v", acls) + } + + if qm.LastIndex == 0 { + t.Fatalf("bad: %v", qm) + } + if !qm.KnownLeader { + t.Fatalf("bad: %v", qm) + } +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/agent.go b/Godeps/_workspace/src/github.com/armon/consul-api/agent.go new file mode 100644 index 00000000..eec93cb9 --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/agent.go @@ -0,0 +1,272 @@ +package consulapi + +import ( + "fmt" +) + +// AgentCheck represents a check known to the agent +type AgentCheck struct { + Node string + CheckID string + Name string + Status string + Notes string + Output string + ServiceID string + ServiceName string +} + +// AgentService represents a service known to the agent +type AgentService struct { + ID string + Service string + Tags []string + Port int +} + +// AgentMember represents a cluster member known to the agent +type AgentMember struct { + Name string + Addr string + Port uint16 + Tags map[string]string + Status int + ProtocolMin uint8 + ProtocolMax uint8 + ProtocolCur uint8 + DelegateMin uint8 + DelegateMax uint8 + DelegateCur uint8 +} + +// AgentServiceRegistration is used to register a new service +type AgentServiceRegistration struct { + ID string `json:",omitempty"` + Name string `json:",omitempty"` + Tags []string `json:",omitempty"` + Port int `json:",omitempty"` + Check *AgentServiceCheck +} + +// AgentCheckRegistration is used to register a new check +type AgentCheckRegistration struct { + ID string `json:",omitempty"` + Name string `json:",omitempty"` + Notes string `json:",omitempty"` + AgentServiceCheck +} + +// AgentServiceCheck is used to create an associated +// check for a service +type AgentServiceCheck struct { + Script string `json:",omitempty"` + Interval string `json:",omitempty"` + TTL string `json:",omitempty"` +} + +// Agent can be used to query the Agent endpoints +type Agent struct { + c *Client + + // cache the node name + nodeName string +} + +// Agent returns a handle to the agent endpoints +func (c *Client) Agent() *Agent { + return &Agent{c: c} +} + +// Self is used to query the agent we are speaking to for +// information about itself +func (a *Agent) Self() (map[string]map[string]interface{}, error) { + r := a.c.newRequest("GET", "/v1/agent/self") + _, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var out map[string]map[string]interface{} + if err := decodeBody(resp, &out); err != nil { + return nil, err + } + return out, nil +} + +// NodeName is used to get the node name of the agent +func (a *Agent) NodeName() (string, error) { + if a.nodeName != "" { + return a.nodeName, nil + } + info, err := a.Self() + if err != nil { + return "", err + } + name := info["Config"]["NodeName"].(string) + a.nodeName = name + return name, nil +} + +// Checks returns the locally registered checks +func (a *Agent) Checks() (map[string]*AgentCheck, error) { + r := a.c.newRequest("GET", "/v1/agent/checks") + _, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var out map[string]*AgentCheck + if err := decodeBody(resp, &out); err != nil { + return nil, err + } + return out, nil +} + +// Services returns the locally registered services +func (a *Agent) Services() (map[string]*AgentService, error) { + r := a.c.newRequest("GET", "/v1/agent/services") + _, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var out map[string]*AgentService + if err := decodeBody(resp, &out); err != nil { + return nil, err + } + return out, nil +} + +// Members returns the known gossip members. The WAN +// flag can be used to query a server for WAN members. +func (a *Agent) Members(wan bool) ([]*AgentMember, error) { + r := a.c.newRequest("GET", "/v1/agent/members") + if wan { + r.params.Set("wan", "1") + } + _, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var out []*AgentMember + if err := decodeBody(resp, &out); err != nil { + return nil, err + } + return out, nil +} + +// ServiceRegister is used to register a new service with +// the local agent +func (a *Agent) ServiceRegister(service *AgentServiceRegistration) error { + r := a.c.newRequest("PUT", "/v1/agent/service/register") + r.obj = service + _, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return err + } + resp.Body.Close() + return nil +} + +// ServiceDeregister is used to deregister a service with +// the local agent +func (a *Agent) ServiceDeregister(serviceID string) error { + r := a.c.newRequest("PUT", "/v1/agent/service/deregister/"+serviceID) + _, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return err + } + resp.Body.Close() + return nil +} + +// PassTTL is used to set a TTL check to the passing state +func (a *Agent) PassTTL(checkID, note string) error { + return a.UpdateTTL(checkID, note, "pass") +} + +// WarnTTL is used to set a TTL check to the warning state +func (a *Agent) WarnTTL(checkID, note string) error { + return a.UpdateTTL(checkID, note, "warn") +} + +// FailTTL is used to set a TTL check to the failing state +func (a *Agent) FailTTL(checkID, note string) error { + return a.UpdateTTL(checkID, note, "fail") +} + +// UpdateTTL is used to update the TTL of a check +func (a *Agent) UpdateTTL(checkID, note, status string) error { + switch status { + case "pass": + case "warn": + case "fail": + default: + return fmt.Errorf("Invalid status: %s", status) + } + endpoint := fmt.Sprintf("/v1/agent/check/%s/%s", status, checkID) + r := a.c.newRequest("PUT", endpoint) + r.params.Set("note", note) + _, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return err + } + resp.Body.Close() + return nil +} + +// CheckRegister is used to register a new check with +// the local agent +func (a *Agent) CheckRegister(check *AgentCheckRegistration) error { + r := a.c.newRequest("PUT", "/v1/agent/check/register") + r.obj = check + _, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return err + } + resp.Body.Close() + return nil +} + +// CheckDeregister is used to deregister a check with +// the local agent +func (a *Agent) CheckDeregister(checkID string) error { + r := a.c.newRequest("PUT", "/v1/agent/check/deregister/"+checkID) + _, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return err + } + resp.Body.Close() + return nil +} + +// Join is used to instruct the agent to attempt a join to +// another cluster member +func (a *Agent) Join(addr string, wan bool) error { + r := a.c.newRequest("PUT", "/v1/agent/join/"+addr) + if wan { + r.params.Set("wan", "1") + } + _, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return err + } + resp.Body.Close() + return nil +} + +// ForceLeave is used to have the agent eject a failed node +func (a *Agent) ForceLeave(node string) error { + r := a.c.newRequest("PUT", "/v1/agent/force-leave/"+node) + _, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return err + } + resp.Body.Close() + return nil +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/agent_test.go b/Godeps/_workspace/src/github.com/armon/consul-api/agent_test.go new file mode 100644 index 00000000..8d97af4a --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/agent_test.go @@ -0,0 +1,162 @@ +package consulapi + +import ( + "testing" +) + +func TestAgent_Self(t *testing.T) { + c := makeClient(t) + agent := c.Agent() + + info, err := agent.Self() + if err != nil { + t.Fatalf("err: %v", err) + } + + name := info["Config"]["NodeName"] + if name == "" { + t.Fatalf("bad: %v", info) + } +} + +func TestAgent_Members(t *testing.T) { + c := makeClient(t) + agent := c.Agent() + + members, err := agent.Members(false) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(members) != 1 { + t.Fatalf("bad: %v", members) + } +} + +func TestAgent_Services(t *testing.T) { + c := makeClient(t) + agent := c.Agent() + + reg := &AgentServiceRegistration{ + Name: "foo", + Tags: []string{"bar", "baz"}, + Port: 8000, + Check: &AgentServiceCheck{ + TTL: "15s", + }, + } + if err := agent.ServiceRegister(reg); err != nil { + t.Fatalf("err: %v", err) + } + + services, err := agent.Services() + if err != nil { + t.Fatalf("err: %v", err) + } + if _, ok := services["foo"]; !ok { + t.Fatalf("missing service: %v", services) + } + + checks, err := agent.Checks() + if err != nil { + t.Fatalf("err: %v", err) + } + if _, ok := checks["service:foo"]; !ok { + t.Fatalf("missing check: %v", checks) + } + + if err := agent.ServiceDeregister("foo"); err != nil { + t.Fatalf("err: %v", err) + } +} + +func TestAgent_SetTTLStatus(t *testing.T) { + c := makeClient(t) + agent := c.Agent() + + reg := &AgentServiceRegistration{ + Name: "foo", + Check: &AgentServiceCheck{ + TTL: "15s", + }, + } + if err := agent.ServiceRegister(reg); err != nil { + t.Fatalf("err: %v", err) + } + + if err := agent.WarnTTL("service:foo", "test"); err != nil { + t.Fatalf("err: %v", err) + } + + checks, err := agent.Checks() + if err != nil { + t.Fatalf("err: %v", err) + } + chk, ok := checks["service:foo"] + if !ok { + t.Fatalf("missing check: %v", checks) + } + if chk.Status != "warning" { + t.Fatalf("Bad: %#v", chk) + } + if chk.Output != "test" { + t.Fatalf("Bad: %#v", chk) + } + + if err := agent.ServiceDeregister("foo"); err != nil { + t.Fatalf("err: %v", err) + } +} + +func TestAgent_Checks(t *testing.T) { + c := makeClient(t) + agent := c.Agent() + + reg := &AgentCheckRegistration{ + Name: "foo", + } + reg.TTL = "15s" + if err := agent.CheckRegister(reg); err != nil { + t.Fatalf("err: %v", err) + } + + checks, err := agent.Checks() + if err != nil { + t.Fatalf("err: %v", err) + } + if _, ok := checks["foo"]; !ok { + t.Fatalf("missing check: %v", checks) + } + + if err := agent.CheckDeregister("foo"); err != nil { + t.Fatalf("err: %v", err) + } +} + +func TestAgent_Join(t *testing.T) { + c := makeClient(t) + agent := c.Agent() + + info, err := agent.Self() + if err != nil { + t.Fatalf("err: %v", err) + } + + // Join ourself + addr := info["Config"]["AdvertiseAddr"].(string) + err = agent.Join(addr, false) + if err != nil { + t.Fatalf("err: %v", err) + } +} + +func TestAgent_ForceLeave(t *testing.T) { + c := makeClient(t) + agent := c.Agent() + + // Eject somebody + err := agent.ForceLeave("foo") + if err != nil { + t.Fatalf("err: %v", err) + } +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/api.go b/Godeps/_workspace/src/github.com/armon/consul-api/api.go new file mode 100644 index 00000000..e1335769 --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/api.go @@ -0,0 +1,323 @@ +package consulapi + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "strconv" + "time" +) + +// QueryOptions are used to parameterize a query +type QueryOptions struct { + // Providing a datacenter overwrites the DC provided + // by the Config + Datacenter string + + // AllowStale allows any Consul server (non-leader) to service + // a read. This allows for lower latency and higher throughput + AllowStale bool + + // RequireConsistent forces the read to be fully consistent. + // This is more expensive but prevents ever performing a stale + // read. + RequireConsistent bool + + // WaitIndex is used to enable a blocking query. Waits + // until the timeout or the next index is reached + WaitIndex uint64 + + // WaitTime is used to bound the duration of a wait. + // Defaults to that of the Config, but can be overriden. + WaitTime time.Duration + + // Token is used to provide a per-request ACL token + // which overrides the agent's default token. + Token string +} + +// WriteOptions are used to parameterize a write +type WriteOptions struct { + // Providing a datacenter overwrites the DC provided + // by the Config + Datacenter string + + // Token is used to provide a per-request ACL token + // which overrides the agent's default token. + Token string +} + +// QueryMeta is used to return meta data about a query +type QueryMeta struct { + // LastIndex. This can be used as a WaitIndex to perform + // a blocking query + LastIndex uint64 + + // Time of last contact from the leader for the + // server servicing the request + LastContact time.Duration + + // Is there a known leader + KnownLeader bool + + // How long did the request take + RequestTime time.Duration +} + +// WriteMeta is used to return meta data about a write +type WriteMeta struct { + // How long did the request take + RequestTime time.Duration +} + +// HttpBasicAuth is used to authenticate http client with HTTP Basic Authentication +type HttpBasicAuth struct { + // Username to use for HTTP Basic Authentication + Username string + + // Password to use for HTTP Basic Authentication + Password string +} + +// Config is used to configure the creation of a client +type Config struct { + // Address is the address of the Consul server + Address string + + // Scheme is the URI scheme for the Consul server + Scheme string + + // Datacenter to use. If not provided, the default agent datacenter is used. + Datacenter string + + // HttpClient is the client to use. Default will be + // used if not provided. + HttpClient *http.Client + + // HttpAuth is the auth info to use for http access. + HttpAuth *HttpBasicAuth + + // WaitTime limits how long a Watch will block. If not provided, + // the agent default values will be used. + WaitTime time.Duration + + // Token is used to provide a per-request ACL token + // which overrides the agent's default token. + Token string +} + +// DefaultConfig returns a default configuration for the client +func DefaultConfig() *Config { + return &Config{ + Address: "127.0.0.1:8500", + Scheme: "http", + HttpClient: http.DefaultClient, + } +} + +// Client provides a client to the Consul API +type Client struct { + config Config +} + +// NewClient returns a new client +func NewClient(config *Config) (*Client, error) { + // bootstrap the config + defConfig := DefaultConfig() + + if len(config.Address) == 0 { + config.Address = defConfig.Address + } + + if len(config.Scheme) == 0 { + config.Scheme = defConfig.Scheme + } + + if config.HttpClient == nil { + config.HttpClient = defConfig.HttpClient + } + + client := &Client{ + config: *config, + } + return client, nil +} + +// request is used to help build up a request +type request struct { + config *Config + method string + url *url.URL + params url.Values + body io.Reader + obj interface{} +} + +// setQueryOptions is used to annotate the request with +// additional query options +func (r *request) setQueryOptions(q *QueryOptions) { + if q == nil { + return + } + if q.Datacenter != "" { + r.params.Set("dc", q.Datacenter) + } + if q.AllowStale { + r.params.Set("stale", "") + } + if q.RequireConsistent { + r.params.Set("consistent", "") + } + if q.WaitIndex != 0 { + r.params.Set("index", strconv.FormatUint(q.WaitIndex, 10)) + } + if q.WaitTime != 0 { + r.params.Set("wait", durToMsec(q.WaitTime)) + } + if q.Token != "" { + r.params.Set("token", q.Token) + } +} + +// durToMsec converts a duration to a millisecond specified string +func durToMsec(dur time.Duration) string { + return fmt.Sprintf("%dms", dur/time.Millisecond) +} + +// setWriteOptions is used to annotate the request with +// additional write options +func (r *request) setWriteOptions(q *WriteOptions) { + if q == nil { + return + } + if q.Datacenter != "" { + r.params.Set("dc", q.Datacenter) + } + if q.Token != "" { + r.params.Set("token", q.Token) + } +} + +// toHTTP converts the request to an HTTP request +func (r *request) toHTTP() (*http.Request, error) { + // Encode the query parameters + r.url.RawQuery = r.params.Encode() + + // Get the url sring + urlRaw := r.url.String() + + // Check if we should encode the body + if r.body == nil && r.obj != nil { + if b, err := encodeBody(r.obj); err != nil { + return nil, err + } else { + r.body = b + } + } + + // Create the HTTP request + req, err := http.NewRequest(r.method, urlRaw, r.body) + + // Setup auth + if err == nil && r.config.HttpAuth != nil { + req.SetBasicAuth(r.config.HttpAuth.Username, r.config.HttpAuth.Password) + } + + return req, err +} + +// newRequest is used to create a new request +func (c *Client) newRequest(method, path string) *request { + r := &request{ + config: &c.config, + method: method, + url: &url.URL{ + Scheme: c.config.Scheme, + Host: c.config.Address, + Path: path, + }, + params: make(map[string][]string), + } + if c.config.Datacenter != "" { + r.params.Set("dc", c.config.Datacenter) + } + if c.config.WaitTime != 0 { + r.params.Set("wait", durToMsec(r.config.WaitTime)) + } + if c.config.Token != "" { + r.params.Set("token", r.config.Token) + } + return r +} + +// doRequest runs a request with our client +func (c *Client) doRequest(r *request) (time.Duration, *http.Response, error) { + req, err := r.toHTTP() + if err != nil { + return 0, nil, err + } + start := time.Now() + resp, err := c.config.HttpClient.Do(req) + diff := time.Now().Sub(start) + return diff, resp, err +} + +// parseQueryMeta is used to help parse query meta-data +func parseQueryMeta(resp *http.Response, q *QueryMeta) error { + header := resp.Header + + // Parse the X-Consul-Index + index, err := strconv.ParseUint(header.Get("X-Consul-Index"), 10, 64) + if err != nil { + return fmt.Errorf("Failed to parse X-Consul-Index: %v", err) + } + q.LastIndex = index + + // Parse the X-Consul-LastContact + last, err := strconv.ParseUint(header.Get("X-Consul-LastContact"), 10, 64) + if err != nil { + return fmt.Errorf("Failed to parse X-Consul-LastContact: %v", err) + } + q.LastContact = time.Duration(last) * time.Millisecond + + // Parse the X-Consul-KnownLeader + switch header.Get("X-Consul-KnownLeader") { + case "true": + q.KnownLeader = true + default: + q.KnownLeader = false + } + return nil +} + +// decodeBody is used to JSON decode a body +func decodeBody(resp *http.Response, out interface{}) error { + dec := json.NewDecoder(resp.Body) + return dec.Decode(out) +} + +// encodeBody is used to encode a request body +func encodeBody(obj interface{}) (io.Reader, error) { + buf := bytes.NewBuffer(nil) + enc := json.NewEncoder(buf) + if err := enc.Encode(obj); err != nil { + return nil, err + } + return buf, nil +} + +// requireOK is used to wrap doRequest and check for a 200 +func requireOK(d time.Duration, resp *http.Response, e error) (time.Duration, *http.Response, error) { + if e != nil { + return d, resp, e + } + if resp.StatusCode != 200 { + var buf bytes.Buffer + io.Copy(&buf, resp.Body) + return d, resp, fmt.Errorf("Unexpected response code: %d (%s)", resp.StatusCode, buf.Bytes()) + } + return d, resp, e +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/api_test.go b/Godeps/_workspace/src/github.com/armon/consul-api/api_test.go new file mode 100644 index 00000000..3a608c53 --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/api_test.go @@ -0,0 +1,126 @@ +package consulapi + +import ( + crand "crypto/rand" + "fmt" + "net/http" + "testing" + "time" +) + +func makeClient(t *testing.T) *Client { + conf := DefaultConfig() + client, err := NewClient(conf) + if err != nil { + t.Fatalf("err: %v", err) + } + return client +} + +func testKey() string { + buf := make([]byte, 16) + if _, err := crand.Read(buf); err != nil { + panic(fmt.Errorf("Failed to read random bytes: %v", err)) + } + + return fmt.Sprintf("%08x-%04x-%04x-%04x-%12x", + buf[0:4], + buf[4:6], + buf[6:8], + buf[8:10], + buf[10:16]) +} + +func TestSetQueryOptions(t *testing.T) { + c := makeClient(t) + r := c.newRequest("GET", "/v1/kv/foo") + q := &QueryOptions{ + Datacenter: "foo", + AllowStale: true, + RequireConsistent: true, + WaitIndex: 1000, + WaitTime: 100 * time.Second, + Token: "12345", + } + r.setQueryOptions(q) + + if r.params.Get("dc") != "foo" { + t.Fatalf("bad: %v", r.params) + } + if _, ok := r.params["stale"]; !ok { + t.Fatalf("bad: %v", r.params) + } + if _, ok := r.params["consistent"]; !ok { + t.Fatalf("bad: %v", r.params) + } + if r.params.Get("index") != "1000" { + t.Fatalf("bad: %v", r.params) + } + if r.params.Get("wait") != "100000ms" { + t.Fatalf("bad: %v", r.params) + } + if r.params.Get("token") != "12345" { + t.Fatalf("bad: %v", r.params) + } +} + +func TestSetWriteOptions(t *testing.T) { + c := makeClient(t) + r := c.newRequest("GET", "/v1/kv/foo") + q := &WriteOptions{ + Datacenter: "foo", + Token: "23456", + } + r.setWriteOptions(q) + + if r.params.Get("dc") != "foo" { + t.Fatalf("bad: %v", r.params) + } + if r.params.Get("token") != "23456" { + t.Fatalf("bad: %v", r.params) + } +} + +func TestRequestToHTTP(t *testing.T) { + c := makeClient(t) + r := c.newRequest("DELETE", "/v1/kv/foo") + q := &QueryOptions{ + Datacenter: "foo", + } + r.setQueryOptions(q) + req, err := r.toHTTP() + if err != nil { + t.Fatalf("err: %v", err) + } + + if req.Method != "DELETE" { + t.Fatalf("bad: %v", req) + } + if req.URL.String() != "http://127.0.0.1:8500/v1/kv/foo?dc=foo" { + t.Fatalf("bad: %v", req) + } +} + +func TestParseQueryMeta(t *testing.T) { + resp := &http.Response{ + Header: make(map[string][]string), + } + resp.Header.Set("X-Consul-Index", "12345") + resp.Header.Set("X-Consul-LastContact", "80") + resp.Header.Set("X-Consul-KnownLeader", "true") + + qm := &QueryMeta{} + if err := parseQueryMeta(resp, qm); err != nil { + t.Fatalf("err: %v", err) + } + + if qm.LastIndex != 12345 { + t.Fatalf("Bad: %v", qm) + } + if qm.LastContact != 80*time.Millisecond { + t.Fatalf("Bad: %v", qm) + } + if !qm.KnownLeader { + t.Fatalf("Bad: %v", qm) + } +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/catalog.go b/Godeps/_workspace/src/github.com/armon/consul-api/catalog.go new file mode 100644 index 00000000..8080e2a9 --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/catalog.go @@ -0,0 +1,181 @@ +package consulapi + +type Node struct { + Node string + Address string +} + +type CatalogService struct { + Node string + Address string + ServiceID string + ServiceName string + ServiceTags []string + ServicePort int +} + +type CatalogNode struct { + Node *Node + Services map[string]*AgentService +} + +type CatalogRegistration struct { + Node string + Address string + Datacenter string + Service *AgentService + Check *AgentCheck +} + +type CatalogDeregistration struct { + Node string + Address string + Datacenter string + ServiceID string + CheckID string +} + +// Catalog can be used to query the Catalog endpoints +type Catalog struct { + c *Client +} + +// Catalog returns a handle to the catalog endpoints +func (c *Client) Catalog() *Catalog { + return &Catalog{c} +} + +func (c *Catalog) Register(reg *CatalogRegistration, q *WriteOptions) (*WriteMeta, error) { + r := c.c.newRequest("PUT", "/v1/catalog/register") + r.setWriteOptions(q) + r.obj = reg + rtt, resp, err := requireOK(c.c.doRequest(r)) + if err != nil { + return nil, err + } + resp.Body.Close() + + wm := &WriteMeta{} + wm.RequestTime = rtt + + return wm, nil +} + +func (c *Catalog) Deregister(dereg *CatalogDeregistration, q *WriteOptions) (*WriteMeta, error) { + r := c.c.newRequest("PUT", "/v1/catalog/deregister") + r.setWriteOptions(q) + r.obj = dereg + rtt, resp, err := requireOK(c.c.doRequest(r)) + if err != nil { + return nil, err + } + resp.Body.Close() + + wm := &WriteMeta{} + wm.RequestTime = rtt + + return wm, nil +} + +// Datacenters is used to query for all the known datacenters +func (c *Catalog) Datacenters() ([]string, error) { + r := c.c.newRequest("GET", "/v1/catalog/datacenters") + _, resp, err := requireOK(c.c.doRequest(r)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var out []string + if err := decodeBody(resp, &out); err != nil { + return nil, err + } + return out, nil +} + +// Nodes is used to query all the known nodes +func (c *Catalog) Nodes(q *QueryOptions) ([]*Node, *QueryMeta, error) { + r := c.c.newRequest("GET", "/v1/catalog/nodes") + r.setQueryOptions(q) + rtt, resp, err := requireOK(c.c.doRequest(r)) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var out []*Node + if err := decodeBody(resp, &out); err != nil { + return nil, nil, err + } + return out, qm, nil +} + +// Services is used to query for all known services +func (c *Catalog) Services(q *QueryOptions) (map[string][]string, *QueryMeta, error) { + r := c.c.newRequest("GET", "/v1/catalog/services") + r.setQueryOptions(q) + rtt, resp, err := requireOK(c.c.doRequest(r)) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var out map[string][]string + if err := decodeBody(resp, &out); err != nil { + return nil, nil, err + } + return out, qm, nil +} + +// Service is used to query catalog entries for a given service +func (c *Catalog) Service(service, tag string, q *QueryOptions) ([]*CatalogService, *QueryMeta, error) { + r := c.c.newRequest("GET", "/v1/catalog/service/"+service) + r.setQueryOptions(q) + if tag != "" { + r.params.Set("tag", tag) + } + rtt, resp, err := requireOK(c.c.doRequest(r)) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var out []*CatalogService + if err := decodeBody(resp, &out); err != nil { + return nil, nil, err + } + return out, qm, nil +} + +// Node is used to query for service information about a single node +func (c *Catalog) Node(node string, q *QueryOptions) (*CatalogNode, *QueryMeta, error) { + r := c.c.newRequest("GET", "/v1/catalog/node/"+node) + r.setQueryOptions(q) + rtt, resp, err := requireOK(c.c.doRequest(r)) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var out *CatalogNode + if err := decodeBody(resp, &out); err != nil { + return nil, nil, err + } + return out, qm, nil +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/catalog_test.go b/Godeps/_workspace/src/github.com/armon/consul-api/catalog_test.go new file mode 100644 index 00000000..7ed6cfc2 --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/catalog_test.go @@ -0,0 +1,219 @@ +package consulapi + +import ( + "testing" +) + +func TestCatalog_Datacenters(t *testing.T) { + c := makeClient(t) + catalog := c.Catalog() + + datacenters, err := catalog.Datacenters() + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(datacenters) == 0 { + t.Fatalf("Bad: %v", datacenters) + } +} + +func TestCatalog_Nodes(t *testing.T) { + c := makeClient(t) + catalog := c.Catalog() + + nodes, meta, err := catalog.Nodes(nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if meta.LastIndex == 0 { + t.Fatalf("Bad: %v", meta) + } + + if len(nodes) == 0 { + t.Fatalf("Bad: %v", nodes) + } +} + +func TestCatalog_Services(t *testing.T) { + c := makeClient(t) + catalog := c.Catalog() + + services, meta, err := catalog.Services(nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if meta.LastIndex == 0 { + t.Fatalf("Bad: %v", meta) + } + + if len(services) == 0 { + t.Fatalf("Bad: %v", services) + } +} + +func TestCatalog_Service(t *testing.T) { + c := makeClient(t) + catalog := c.Catalog() + + services, meta, err := catalog.Service("consul", "", nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if meta.LastIndex == 0 { + t.Fatalf("Bad: %v", meta) + } + + if len(services) == 0 { + t.Fatalf("Bad: %v", services) + } +} + +func TestCatalog_Node(t *testing.T) { + c := makeClient(t) + catalog := c.Catalog() + + name, _ := c.Agent().NodeName() + info, meta, err := catalog.Node(name, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if meta.LastIndex == 0 { + t.Fatalf("Bad: %v", meta) + } + if len(info.Services) == 0 { + t.Fatalf("Bad: %v", info) + } +} + +func TestCatalog_Registration(t *testing.T) { + c := makeClient(t) + catalog := c.Catalog() + + service := &AgentService{ + ID: "redis1", + Service: "redis", + Tags: []string{"master", "v1"}, + Port: 8000, + } + + check := &AgentCheck{ + Node: "foobar", + CheckID: "service:redis1", + Name: "Redis health check", + Notes: "Script based health check", + Status: "passing", + ServiceID: "redis1", + } + + reg := &CatalogRegistration{ + Datacenter: "dc1", + Node: "foobar", + Address: "192.168.10.10", + Service: service, + Check: check, + } + + _, err := catalog.Register(reg, nil) + + if err != nil { + t.Fatalf("err: %v", err) + } + + node, _, err := catalog.Node("foobar", nil) + + if err != nil { + t.Fatalf("err: %v", err) + } + + if _, ok := node.Services["redis1"]; !ok { + t.Fatalf("missing service: redis1") + } + + health, _, err := c.Health().Node("foobar", nil) + + if err != nil { + t.Fatalf("err: %v", err) + } + + if health[0].CheckID != "service:redis1" { + t.Fatalf("missing checkid service:redis1") + } +} + +func TestCatalog_Deregistration(t *testing.T) { + c := makeClient(t) + catalog := c.Catalog() + + dereg := &CatalogDeregistration{ + Datacenter: "dc1", + Node: "foobar", + Address: "192.168.10.10", + ServiceID: "redis1", + } + + _, err := catalog.Deregister(dereg, nil) + + if err != nil { + t.Fatalf("err: %v", err) + } + + node, _, err := catalog.Node("foobar", nil) + + if err != nil { + t.Fatalf("err: %v", err) + } + + if _, ok := node.Services["redis1"]; ok { + t.Fatalf("ServiceID:redis1 is not deregistered") + } + + dereg = &CatalogDeregistration{ + Datacenter: "dc1", + Node: "foobar", + Address: "192.168.10.10", + CheckID: "service:redis1", + } + + _, err = catalog.Deregister(dereg, nil) + + if err != nil { + t.Fatalf("err: %v", err) + } + + health, _, err := c.Health().Node("foobar", nil) + + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(health) != 0 { + t.Fatalf("CheckID:service:redis1 is not deregistered") + } + + dereg = &CatalogDeregistration{ + Datacenter: "dc1", + Node: "foobar", + Address: "192.168.10.10", + } + + _, err = catalog.Deregister(dereg, nil) + + if err != nil { + t.Fatalf("err: %v", err) + } + + node, _, err = catalog.Node("foobar", nil) + + if err != nil { + t.Fatalf("err: %v", err) + } + + if node != nil { + t.Fatalf("node is not deregistered: %v", node) + } +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/event.go b/Godeps/_workspace/src/github.com/armon/consul-api/event.go new file mode 100644 index 00000000..59813d40 --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/event.go @@ -0,0 +1,104 @@ +package consulapi + +import ( + "bytes" + "strconv" +) + +// Event can be used to query the Event endpoints +type Event struct { + c *Client +} + +// UserEvent represents an event that was fired by the user +type UserEvent struct { + ID string + Name string + Payload []byte + NodeFilter string + ServiceFilter string + TagFilter string + Version int + LTime uint64 +} + +// Event returns a handle to the event endpoints +func (c *Client) Event() *Event { + return &Event{c} +} + +// Fire is used to fire a new user event. Only the Name, Payload and Filters +// are respected. This returns the ID or an associated error. Cross DC requests +// are supported. +func (e *Event) Fire(params *UserEvent, q *WriteOptions) (string, *WriteMeta, error) { + r := e.c.newRequest("PUT", "/v1/event/fire/"+params.Name) + r.setWriteOptions(q) + if params.NodeFilter != "" { + r.params.Set("node", params.NodeFilter) + } + if params.ServiceFilter != "" { + r.params.Set("service", params.ServiceFilter) + } + if params.TagFilter != "" { + r.params.Set("tag", params.TagFilter) + } + if params.Payload != nil { + r.body = bytes.NewReader(params.Payload) + } + + rtt, resp, err := requireOK(e.c.doRequest(r)) + if err != nil { + return "", nil, err + } + defer resp.Body.Close() + + wm := &WriteMeta{RequestTime: rtt} + var out UserEvent + if err := decodeBody(resp, &out); err != nil { + return "", nil, err + } + return out.ID, wm, nil +} + +// List is used to get the most recent events an agent has received. +// This list can be optionally filtered by the name. This endpoint supports +// quasi-blocking queries. The index is not monotonic, nor does it provide provide +// LastContact or KnownLeader. +func (e *Event) List(name string, q *QueryOptions) ([]*UserEvent, *QueryMeta, error) { + r := e.c.newRequest("GET", "/v1/event/list") + r.setQueryOptions(q) + if name != "" { + r.params.Set("name", name) + } + rtt, resp, err := requireOK(e.c.doRequest(r)) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var entries []*UserEvent + if err := decodeBody(resp, &entries); err != nil { + return nil, nil, err + } + return entries, qm, nil +} + +// IDToIndex is a bit of a hack. This simulates the index generation to +// convert an event ID into a WaitIndex. +func (e *Event) IDToIndex(uuid string) uint64 { + lower := uuid[0:8] + uuid[9:13] + uuid[14:18] + upper := uuid[19:23] + uuid[24:36] + lowVal, err := strconv.ParseUint(lower, 16, 64) + if err != nil { + panic("Failed to convert " + lower) + } + highVal, err := strconv.ParseUint(upper, 16, 64) + if err != nil { + panic("Failed to convert " + upper) + } + return lowVal ^ highVal +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/event_test.go b/Godeps/_workspace/src/github.com/armon/consul-api/event_test.go new file mode 100644 index 00000000..f2be010a --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/event_test.go @@ -0,0 +1,37 @@ +package consulapi + +import ( + "testing" +) + +func TestEvent_FireList(t *testing.T) { + c := makeClient(t) + event := c.Event() + + params := &UserEvent{Name: "foo"} + id, meta, err := event.Fire(params, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if meta.RequestTime == 0 { + t.Fatalf("bad: %v", meta) + } + + if id == "" { + t.Fatalf("invalid: %v", id) + } + + events, qm, err := event.List("", nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if qm.LastIndex != event.IDToIndex(id) { + t.Fatalf("Bad: %#v", qm) + } + + if events[len(events)-1].ID != id { + t.Fatalf("bad: %#v", events) + } +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/health.go b/Godeps/_workspace/src/github.com/armon/consul-api/health.go new file mode 100644 index 00000000..574801e2 --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/health.go @@ -0,0 +1,136 @@ +package consulapi + +import ( + "fmt" +) + +// HealthCheck is used to represent a single check +type HealthCheck struct { + Node string + CheckID string + Name string + Status string + Notes string + Output string + ServiceID string + ServiceName string +} + +// ServiceEntry is used for the health service endpoint +type ServiceEntry struct { + Node *Node + Service *AgentService + Checks []*HealthCheck +} + +// Health can be used to query the Health endpoints +type Health struct { + c *Client +} + +// Health returns a handle to the health endpoints +func (c *Client) Health() *Health { + return &Health{c} +} + +// Node is used to query for checks belonging to a given node +func (h *Health) Node(node string, q *QueryOptions) ([]*HealthCheck, *QueryMeta, error) { + r := h.c.newRequest("GET", "/v1/health/node/"+node) + r.setQueryOptions(q) + rtt, resp, err := requireOK(h.c.doRequest(r)) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var out []*HealthCheck + if err := decodeBody(resp, &out); err != nil { + return nil, nil, err + } + return out, qm, nil +} + +// Checks is used to return the checks associated with a service +func (h *Health) Checks(service string, q *QueryOptions) ([]*HealthCheck, *QueryMeta, error) { + r := h.c.newRequest("GET", "/v1/health/checks/"+service) + r.setQueryOptions(q) + rtt, resp, err := requireOK(h.c.doRequest(r)) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var out []*HealthCheck + if err := decodeBody(resp, &out); err != nil { + return nil, nil, err + } + return out, qm, nil +} + +// Service is used to query health information along with service info +// for a given service. It can optionally do server-side filtering on a tag +// or nodes with passing health checks only. +func (h *Health) Service(service, tag string, passingOnly bool, q *QueryOptions) ([]*ServiceEntry, *QueryMeta, error) { + r := h.c.newRequest("GET", "/v1/health/service/"+service) + r.setQueryOptions(q) + if tag != "" { + r.params.Set("tag", tag) + } + if passingOnly { + r.params.Set("passing", "1") + } + rtt, resp, err := requireOK(h.c.doRequest(r)) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var out []*ServiceEntry + if err := decodeBody(resp, &out); err != nil { + return nil, nil, err + } + return out, qm, nil +} + +// State is used to retreive all the checks in a given state. +// The wildcard "any" state can also be used for all checks. +func (h *Health) State(state string, q *QueryOptions) ([]*HealthCheck, *QueryMeta, error) { + switch state { + case "any": + case "warning": + case "critical": + case "passing": + case "unknown": + default: + return nil, nil, fmt.Errorf("Unsupported state: %v", state) + } + r := h.c.newRequest("GET", "/v1/health/state/"+state) + r.setQueryOptions(q) + rtt, resp, err := requireOK(h.c.doRequest(r)) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var out []*HealthCheck + if err := decodeBody(resp, &out); err != nil { + return nil, nil, err + } + return out, qm, nil +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/health_test.go b/Godeps/_workspace/src/github.com/armon/consul-api/health_test.go new file mode 100644 index 00000000..d2b3da2e --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/health_test.go @@ -0,0 +1,98 @@ +package consulapi + +import ( + "testing" + "time" +) + +func TestHealth_Node(t *testing.T) { + c := makeClient(t) + agent := c.Agent() + health := c.Health() + + info, err := agent.Self() + if err != nil { + t.Fatalf("err: %v", err) + } + name := info["Config"]["NodeName"].(string) + + checks, meta, err := health.Node(name, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if meta.LastIndex == 0 { + t.Fatalf("bad: %v", meta) + } + if len(checks) == 0 { + t.Fatalf("Bad: %v", checks) + } +} + +func TestHealth_Checks(t *testing.T) { + c := makeClient(t) + agent := c.Agent() + health := c.Health() + + // Make a service with a check + reg := &AgentServiceRegistration{ + Name: "foo", + Check: &AgentServiceCheck{ + TTL: "15s", + }, + } + if err := agent.ServiceRegister(reg); err != nil { + t.Fatalf("err: %v", err) + } + defer agent.ServiceDeregister("foo") + + // Wait for the register... + time.Sleep(20 * time.Millisecond) + + checks, meta, err := health.Checks("foo", nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if meta.LastIndex == 0 { + t.Fatalf("bad: %v", meta) + } + if len(checks) == 0 { + t.Fatalf("Bad: %v", checks) + } +} + +func TestHealth_Service(t *testing.T) { + c := makeClient(t) + health := c.Health() + + // consul service should always exist... + checks, meta, err := health.Service("consul", "", true, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if meta.LastIndex == 0 { + t.Fatalf("bad: %v", meta) + } + if len(checks) == 0 { + t.Fatalf("Bad: %v", checks) + } +} + +func TestHealth_State(t *testing.T) { + c := makeClient(t) + health := c.Health() + + checks, meta, err := health.State("any", nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if meta.LastIndex == 0 { + t.Fatalf("bad: %v", meta) + } + if len(checks) == 0 { + t.Fatalf("Bad: %v", checks) + } +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/kv.go b/Godeps/_workspace/src/github.com/armon/consul-api/kv.go new file mode 100644 index 00000000..98c3b1a0 --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/kv.go @@ -0,0 +1,219 @@ +package consulapi + +import ( + "bytes" + "fmt" + "io" + "net/http" + "strconv" + "strings" +) + +// KVPair is used to represent a single K/V entry +type KVPair struct { + Key string + CreateIndex uint64 + ModifyIndex uint64 + LockIndex uint64 + Flags uint64 + Value []byte + Session string +} + +// KVPairs is a list of KVPair objects +type KVPairs []*KVPair + +// KV is used to manipulate the K/V API +type KV struct { + c *Client +} + +// KV is used to return a handle to the K/V apis +func (c *Client) KV() *KV { + return &KV{c} +} + +// Get is used to lookup a single key +func (k *KV) Get(key string, q *QueryOptions) (*KVPair, *QueryMeta, error) { + resp, qm, err := k.getInternal(key, nil, q) + if err != nil { + return nil, nil, err + } + if resp == nil { + return nil, qm, nil + } + defer resp.Body.Close() + + var entries []*KVPair + if err := decodeBody(resp, &entries); err != nil { + return nil, nil, err + } + if len(entries) > 0 { + return entries[0], qm, nil + } + return nil, qm, nil +} + +// List is used to lookup all keys under a prefix +func (k *KV) List(prefix string, q *QueryOptions) (KVPairs, *QueryMeta, error) { + resp, qm, err := k.getInternal(prefix, map[string]string{"recurse": ""}, q) + if err != nil { + return nil, nil, err + } + if resp == nil { + return nil, qm, nil + } + defer resp.Body.Close() + + var entries []*KVPair + if err := decodeBody(resp, &entries); err != nil { + return nil, nil, err + } + return entries, qm, nil +} + +// Keys is used to list all the keys under a prefix. Optionally, +// a separator can be used to limit the responses. +func (k *KV) Keys(prefix, separator string, q *QueryOptions) ([]string, *QueryMeta, error) { + params := map[string]string{"keys": ""} + if separator != "" { + params["separator"] = separator + } + resp, qm, err := k.getInternal(prefix, params, q) + if err != nil { + return nil, nil, err + } + if resp == nil { + return nil, qm, nil + } + defer resp.Body.Close() + + var entries []string + if err := decodeBody(resp, &entries); err != nil { + return nil, nil, err + } + return entries, qm, nil +} + +func (k *KV) getInternal(key string, params map[string]string, q *QueryOptions) (*http.Response, *QueryMeta, error) { + r := k.c.newRequest("GET", "/v1/kv/"+key) + r.setQueryOptions(q) + for param, val := range params { + r.params.Set(param, val) + } + rtt, resp, err := k.c.doRequest(r) + if err != nil { + return nil, nil, err + } + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + if resp.StatusCode == 404 { + resp.Body.Close() + return nil, qm, nil + } else if resp.StatusCode != 200 { + resp.Body.Close() + return nil, nil, fmt.Errorf("Unexpected response code: %d", resp.StatusCode) + } + return resp, qm, nil +} + +// Put is used to write a new value. Only the +// Key, Flags and Value is respected. +func (k *KV) Put(p *KVPair, q *WriteOptions) (*WriteMeta, error) { + params := make(map[string]string, 1) + if p.Flags != 0 { + params["flags"] = strconv.FormatUint(p.Flags, 10) + } + _, wm, err := k.put(p.Key, params, p.Value, q) + return wm, err +} + +// CAS is used for a Check-And-Set operation. The Key, +// ModifyIndex, Flags and Value are respected. Returns true +// on success or false on failures. +func (k *KV) CAS(p *KVPair, q *WriteOptions) (bool, *WriteMeta, error) { + params := make(map[string]string, 2) + if p.Flags != 0 { + params["flags"] = strconv.FormatUint(p.Flags, 10) + } + params["cas"] = strconv.FormatUint(p.ModifyIndex, 10) + return k.put(p.Key, params, p.Value, q) +} + +// Acquire is used for a lock acquisiiton operation. The Key, +// Flags, Value and Session are respected. Returns true +// on success or false on failures. +func (k *KV) Acquire(p *KVPair, q *WriteOptions) (bool, *WriteMeta, error) { + params := make(map[string]string, 2) + if p.Flags != 0 { + params["flags"] = strconv.FormatUint(p.Flags, 10) + } + params["acquire"] = p.Session + return k.put(p.Key, params, p.Value, q) +} + +// Release is used for a lock release operation. The Key, +// Flags, Value and Session are respected. Returns true +// on success or false on failures. +func (k *KV) Release(p *KVPair, q *WriteOptions) (bool, *WriteMeta, error) { + params := make(map[string]string, 2) + if p.Flags != 0 { + params["flags"] = strconv.FormatUint(p.Flags, 10) + } + params["release"] = p.Session + return k.put(p.Key, params, p.Value, q) +} + +func (k *KV) put(key string, params map[string]string, body []byte, q *WriteOptions) (bool, *WriteMeta, error) { + r := k.c.newRequest("PUT", "/v1/kv/"+key) + r.setWriteOptions(q) + for param, val := range params { + r.params.Set(param, val) + } + r.body = bytes.NewReader(body) + rtt, resp, err := requireOK(k.c.doRequest(r)) + if err != nil { + return false, nil, err + } + defer resp.Body.Close() + + qm := &WriteMeta{} + qm.RequestTime = rtt + + var buf bytes.Buffer + if _, err := io.Copy(&buf, resp.Body); err != nil { + return false, nil, fmt.Errorf("Failed to read response: %v", err) + } + res := strings.Contains(string(buf.Bytes()), "true") + return res, qm, nil +} + +// Delete is used to delete a single key +func (k *KV) Delete(key string, w *WriteOptions) (*WriteMeta, error) { + return k.deleteInternal(key, nil, w) +} + +// DeleteTree is used to delete all keys under a prefix +func (k *KV) DeleteTree(prefix string, w *WriteOptions) (*WriteMeta, error) { + return k.deleteInternal(prefix, []string{"recurse"}, w) +} + +func (k *KV) deleteInternal(key string, params []string, q *WriteOptions) (*WriteMeta, error) { + r := k.c.newRequest("DELETE", "/v1/kv/"+key) + r.setWriteOptions(q) + for _, param := range params { + r.params.Set(param, "") + } + rtt, resp, err := requireOK(k.c.doRequest(r)) + if err != nil { + return nil, err + } + resp.Body.Close() + + qm := &WriteMeta{} + qm.RequestTime = rtt + return qm, nil +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/kv_test.go b/Godeps/_workspace/src/github.com/armon/consul-api/kv_test.go new file mode 100644 index 00000000..2d92d69f --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/kv_test.go @@ -0,0 +1,374 @@ +package consulapi + +import ( + "bytes" + "path" + "testing" + "time" +) + +func TestClientPutGetDelete(t *testing.T) { + c := makeClient(t) + kv := c.KV() + + // Get a get without a key + key := testKey() + pair, _, err := kv.Get(key, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + if pair != nil { + t.Fatalf("unexpected value: %#v", pair) + } + + // Put the key + value := []byte("test") + p := &KVPair{Key: key, Flags: 42, Value: value} + if _, err := kv.Put(p, nil); err != nil { + t.Fatalf("err: %v", err) + } + + // Get should work + pair, meta, err := kv.Get(key, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + if pair == nil { + t.Fatalf("expected value: %#v", pair) + } + if !bytes.Equal(pair.Value, value) { + t.Fatalf("unexpected value: %#v", pair) + } + if pair.Flags != 42 { + t.Fatalf("unexpected value: %#v", pair) + } + if meta.LastIndex == 0 { + t.Fatalf("unexpected value: %#v", meta) + } + + // Delete + if _, err := kv.Delete(key, nil); err != nil { + t.Fatalf("err: %v", err) + } + + // Get should fail + pair, _, err = kv.Get(key, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + if pair != nil { + t.Fatalf("unexpected value: %#v", pair) + } +} + +func TestClient_List_DeleteRecurse(t *testing.T) { + c := makeClient(t) + kv := c.KV() + + // Generate some test keys + prefix := testKey() + var keys []string + for i := 0; i < 100; i++ { + keys = append(keys, path.Join(prefix, testKey())) + } + + // Set values + value := []byte("test") + for _, key := range keys { + p := &KVPair{Key: key, Value: value} + if _, err := kv.Put(p, nil); err != nil { + t.Fatalf("err: %v", err) + } + } + + // List the values + pairs, meta, err := kv.List(prefix, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + if len(pairs) != len(keys) { + t.Fatalf("got %d keys", len(pairs)) + } + for _, pair := range pairs { + if !bytes.Equal(pair.Value, value) { + t.Fatalf("unexpected value: %#v", pair) + } + } + if meta.LastIndex == 0 { + t.Fatalf("unexpected value: %#v", meta) + } + + // Delete all + if _, err := kv.DeleteTree(prefix, nil); err != nil { + t.Fatalf("err: %v", err) + } + + // List the values + pairs, _, err = kv.List(prefix, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + if len(pairs) != 0 { + t.Fatalf("got %d keys", len(pairs)) + } +} + +func TestClient_CAS(t *testing.T) { + c := makeClient(t) + kv := c.KV() + + // Put the key + key := testKey() + value := []byte("test") + p := &KVPair{Key: key, Value: value} + if work, _, err := kv.CAS(p, nil); err != nil { + t.Fatalf("err: %v", err) + } else if !work { + t.Fatalf("CAS failure") + } + + // Get should work + pair, meta, err := kv.Get(key, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + if pair == nil { + t.Fatalf("expected value: %#v", pair) + } + if meta.LastIndex == 0 { + t.Fatalf("unexpected value: %#v", meta) + } + + // CAS update with bad index + newVal := []byte("foo") + p.Value = newVal + p.ModifyIndex = 1 + if work, _, err := kv.CAS(p, nil); err != nil { + t.Fatalf("err: %v", err) + } else if work { + t.Fatalf("unexpected CAS") + } + + // CAS update with valid index + p.ModifyIndex = meta.LastIndex + if work, _, err := kv.CAS(p, nil); err != nil { + t.Fatalf("err: %v", err) + } else if !work { + t.Fatalf("unexpected CAS failure") + } +} + +func TestClient_WatchGet(t *testing.T) { + c := makeClient(t) + kv := c.KV() + + // Get a get without a key + key := testKey() + pair, meta, err := kv.Get(key, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + if pair != nil { + t.Fatalf("unexpected value: %#v", pair) + } + if meta.LastIndex == 0 { + t.Fatalf("unexpected value: %#v", meta) + } + + // Put the key + value := []byte("test") + go func() { + c := makeClient(t) + kv := c.KV() + + time.Sleep(100 * time.Millisecond) + p := &KVPair{Key: key, Flags: 42, Value: value} + if _, err := kv.Put(p, nil); err != nil { + t.Fatalf("err: %v", err) + } + }() + + // Get should work + options := &QueryOptions{WaitIndex: meta.LastIndex} + pair, meta2, err := kv.Get(key, options) + if err != nil { + t.Fatalf("err: %v", err) + } + if pair == nil { + t.Fatalf("expected value: %#v", pair) + } + if !bytes.Equal(pair.Value, value) { + t.Fatalf("unexpected value: %#v", pair) + } + if pair.Flags != 42 { + t.Fatalf("unexpected value: %#v", pair) + } + if meta2.LastIndex <= meta.LastIndex { + t.Fatalf("unexpected value: %#v", meta2) + } +} + +func TestClient_WatchList(t *testing.T) { + c := makeClient(t) + kv := c.KV() + + // Get a get without a key + prefix := testKey() + key := path.Join(prefix, testKey()) + pairs, meta, err := kv.List(prefix, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + if len(pairs) != 0 { + t.Fatalf("unexpected value: %#v", pairs) + } + if meta.LastIndex == 0 { + t.Fatalf("unexpected value: %#v", meta) + } + + // Put the key + value := []byte("test") + go func() { + c := makeClient(t) + kv := c.KV() + + time.Sleep(100 * time.Millisecond) + p := &KVPair{Key: key, Flags: 42, Value: value} + if _, err := kv.Put(p, nil); err != nil { + t.Fatalf("err: %v", err) + } + }() + + // Get should work + options := &QueryOptions{WaitIndex: meta.LastIndex} + pairs, meta2, err := kv.List(prefix, options) + if err != nil { + t.Fatalf("err: %v", err) + } + if len(pairs) != 1 { + t.Fatalf("expected value: %#v", pairs) + } + if !bytes.Equal(pairs[0].Value, value) { + t.Fatalf("unexpected value: %#v", pairs) + } + if pairs[0].Flags != 42 { + t.Fatalf("unexpected value: %#v", pairs) + } + if meta2.LastIndex <= meta.LastIndex { + t.Fatalf("unexpected value: %#v", meta2) + } + +} + +func TestClient_Keys_DeleteRecurse(t *testing.T) { + c := makeClient(t) + kv := c.KV() + + // Generate some test keys + prefix := testKey() + var keys []string + for i := 0; i < 100; i++ { + keys = append(keys, path.Join(prefix, testKey())) + } + + // Set values + value := []byte("test") + for _, key := range keys { + p := &KVPair{Key: key, Value: value} + if _, err := kv.Put(p, nil); err != nil { + t.Fatalf("err: %v", err) + } + } + + // List the values + out, meta, err := kv.Keys(prefix, "", nil) + if err != nil { + t.Fatalf("err: %v", err) + } + if len(out) != len(keys) { + t.Fatalf("got %d keys", len(out)) + } + if meta.LastIndex == 0 { + t.Fatalf("unexpected value: %#v", meta) + } + + // Delete all + if _, err := kv.DeleteTree(prefix, nil); err != nil { + t.Fatalf("err: %v", err) + } + + // List the values + out, _, err = kv.Keys(prefix, "", nil) + if err != nil { + t.Fatalf("err: %v", err) + } + if len(out) != 0 { + t.Fatalf("got %d keys", len(out)) + } +} + +func TestClient_AcquireRelease(t *testing.T) { + c := makeClient(t) + session := c.Session() + kv := c.KV() + + // Make a session + id, _, err := session.CreateNoChecks(nil, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + defer session.Destroy(id, nil) + + // Acquire the key + key := testKey() + value := []byte("test") + p := &KVPair{Key: key, Value: value, Session: id} + if work, _, err := kv.Acquire(p, nil); err != nil { + t.Fatalf("err: %v", err) + } else if !work { + t.Fatalf("Lock failure") + } + + // Get should work + pair, meta, err := kv.Get(key, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + if pair == nil { + t.Fatalf("expected value: %#v", pair) + } + if pair.LockIndex != 1 { + t.Fatalf("Expected lock: %v", pair) + } + if pair.Session != id { + t.Fatalf("Expected lock: %v", pair) + } + if meta.LastIndex == 0 { + t.Fatalf("unexpected value: %#v", meta) + } + + // Release + if work, _, err := kv.Release(p, nil); err != nil { + t.Fatalf("err: %v", err) + } else if !work { + t.Fatalf("Release fail") + } + + // Get should work + pair, meta, err = kv.Get(key, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + if pair == nil { + t.Fatalf("expected value: %#v", pair) + } + if pair.LockIndex != 1 { + t.Fatalf("Expected lock: %v", pair) + } + if pair.Session != "" { + t.Fatalf("Expected unlock: %v", pair) + } + if meta.LastIndex == 0 { + t.Fatalf("unexpected value: %#v", meta) + } +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/session.go b/Godeps/_workspace/src/github.com/armon/consul-api/session.go new file mode 100644 index 00000000..4fbfc5ee --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/session.go @@ -0,0 +1,204 @@ +package consulapi + +import ( + "time" +) + +// SessionEntry represents a session in consul +type SessionEntry struct { + CreateIndex uint64 + ID string + Name string + Node string + Checks []string + LockDelay time.Duration + Behavior string + TTL string +} + +// Session can be used to query the Session endpoints +type Session struct { + c *Client +} + +// Session returns a handle to the session endpoints +func (c *Client) Session() *Session { + return &Session{c} +} + +// CreateNoChecks is like Create but is used specifically to create +// a session with no associated health checks. +func (s *Session) CreateNoChecks(se *SessionEntry, q *WriteOptions) (string, *WriteMeta, error) { + body := make(map[string]interface{}) + body["Checks"] = []string{} + if se != nil { + if se.Name != "" { + body["Name"] = se.Name + } + if se.Node != "" { + body["Node"] = se.Node + } + if se.LockDelay != 0 { + body["LockDelay"] = durToMsec(se.LockDelay) + } + if se.Behavior != "" { + body["Behavior"] = se.Behavior + } + if se.TTL != "" { + body["TTL"] = se.TTL + } + } + return s.create(body, q) + +} + +// Create makes a new session. Providing a session entry can +// customize the session. It can also be nil to use defaults. +func (s *Session) Create(se *SessionEntry, q *WriteOptions) (string, *WriteMeta, error) { + var obj interface{} + if se != nil { + body := make(map[string]interface{}) + obj = body + if se.Name != "" { + body["Name"] = se.Name + } + if se.Node != "" { + body["Node"] = se.Node + } + if se.LockDelay != 0 { + body["LockDelay"] = durToMsec(se.LockDelay) + } + if len(se.Checks) > 0 { + body["Checks"] = se.Checks + } + if se.Behavior != "" { + body["Behavior"] = se.Behavior + } + if se.TTL != "" { + body["TTL"] = se.TTL + } + } + return s.create(obj, q) +} + +func (s *Session) create(obj interface{}, q *WriteOptions) (string, *WriteMeta, error) { + r := s.c.newRequest("PUT", "/v1/session/create") + r.setWriteOptions(q) + r.obj = obj + rtt, resp, err := requireOK(s.c.doRequest(r)) + if err != nil { + return "", nil, err + } + defer resp.Body.Close() + + wm := &WriteMeta{RequestTime: rtt} + var out struct{ ID string } + if err := decodeBody(resp, &out); err != nil { + return "", nil, err + } + return out.ID, wm, nil +} + +// Destroy invalides a given session +func (s *Session) Destroy(id string, q *WriteOptions) (*WriteMeta, error) { + r := s.c.newRequest("PUT", "/v1/session/destroy/"+id) + r.setWriteOptions(q) + rtt, resp, err := requireOK(s.c.doRequest(r)) + if err != nil { + return nil, err + } + resp.Body.Close() + + wm := &WriteMeta{RequestTime: rtt} + return wm, nil +} + +// Renew renews the TTL on a given session +func (s *Session) Renew(id string, q *WriteOptions) (*SessionEntry, *WriteMeta, error) { + r := s.c.newRequest("PUT", "/v1/session/renew/"+id) + r.setWriteOptions(q) + rtt, resp, err := requireOK(s.c.doRequest(r)) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + wm := &WriteMeta{RequestTime: rtt} + + var entries []*SessionEntry + if err := decodeBody(resp, &entries); err != nil { + return nil, wm, err + } + + if len(entries) > 0 { + return entries[0], wm, nil + } + return nil, wm, nil +} + +// Info looks up a single session +func (s *Session) Info(id string, q *QueryOptions) (*SessionEntry, *QueryMeta, error) { + r := s.c.newRequest("GET", "/v1/session/info/"+id) + r.setQueryOptions(q) + rtt, resp, err := requireOK(s.c.doRequest(r)) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var entries []*SessionEntry + if err := decodeBody(resp, &entries); err != nil { + return nil, nil, err + } + + if len(entries) > 0 { + return entries[0], qm, nil + } + return nil, qm, nil +} + +// List gets sessions for a node +func (s *Session) Node(node string, q *QueryOptions) ([]*SessionEntry, *QueryMeta, error) { + r := s.c.newRequest("GET", "/v1/session/node/"+node) + r.setQueryOptions(q) + rtt, resp, err := requireOK(s.c.doRequest(r)) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var entries []*SessionEntry + if err := decodeBody(resp, &entries); err != nil { + return nil, nil, err + } + return entries, qm, nil +} + +// List gets all active sessions +func (s *Session) List(q *QueryOptions) ([]*SessionEntry, *QueryMeta, error) { + r := s.c.newRequest("GET", "/v1/session/list") + r.setQueryOptions(q) + rtt, resp, err := requireOK(s.c.doRequest(r)) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var entries []*SessionEntry + if err := decodeBody(resp, &entries); err != nil { + return nil, nil, err + } + return entries, qm, nil +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/session_test.go b/Godeps/_workspace/src/github.com/armon/consul-api/session_test.go new file mode 100644 index 00000000..9351c999 --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/session_test.go @@ -0,0 +1,190 @@ +package consulapi + +import ( + "testing" +) + +func TestSession_CreateDestroy(t *testing.T) { + c := makeClient(t) + session := c.Session() + + id, meta, err := session.Create(nil, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if meta.RequestTime == 0 { + t.Fatalf("bad: %v", meta) + } + + if id == "" { + t.Fatalf("invalid: %v", id) + } + + meta, err = session.Destroy(id, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if meta.RequestTime == 0 { + t.Fatalf("bad: %v", meta) + } +} + +func TestSession_CreateRenewDestroy(t *testing.T) { + c := makeClient(t) + session := c.Session() + + se := &SessionEntry{ + TTL: "10s", + } + + id, meta, err := session.Create(se, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + defer session.Destroy(id, nil) + + if meta.RequestTime == 0 { + t.Fatalf("bad: %v", meta) + } + + if id == "" { + t.Fatalf("invalid: %v", id) + } + + if meta.RequestTime == 0 { + t.Fatalf("bad: %v", meta) + } + + renew, meta, err := session.Renew(id, nil) + + if err != nil { + t.Fatalf("err: %v", err) + } + if meta.RequestTime == 0 { + t.Fatalf("bad: %v", meta) + } + + if renew == nil { + t.Fatalf("should get session") + } + + if renew.ID != id { + t.Fatalf("should have matching id") + } + + if renew.TTL != "10s" { + t.Fatalf("should get session with TTL") + } +} + +func TestSession_Info(t *testing.T) { + c := makeClient(t) + session := c.Session() + + id, _, err := session.Create(nil, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + defer session.Destroy(id, nil) + + info, qm, err := session.Info(id, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if qm.LastIndex == 0 { + t.Fatalf("bad: %v", qm) + } + if !qm.KnownLeader { + t.Fatalf("bad: %v", qm) + } + + if info == nil { + t.Fatalf("should get session") + } + if info.CreateIndex == 0 { + t.Fatalf("bad: %v", info) + } + if info.ID != id { + t.Fatalf("bad: %v", info) + } + if info.Name != "" { + t.Fatalf("bad: %v", info) + } + if info.Node == "" { + t.Fatalf("bad: %v", info) + } + if len(info.Checks) == 0 { + t.Fatalf("bad: %v", info) + } + if info.LockDelay == 0 { + t.Fatalf("bad: %v", info) + } + if info.Behavior != "release" { + t.Fatalf("bad: %v", info) + } + if info.TTL != "" { + t.Fatalf("bad: %v", info) + } +} + +func TestSession_Node(t *testing.T) { + c := makeClient(t) + session := c.Session() + + id, _, err := session.Create(nil, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + defer session.Destroy(id, nil) + + info, qm, err := session.Info(id, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + sessions, qm, err := session.Node(info.Node, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(sessions) != 1 { + t.Fatalf("bad: %v", sessions) + } + + if qm.LastIndex == 0 { + t.Fatalf("bad: %v", qm) + } + if !qm.KnownLeader { + t.Fatalf("bad: %v", qm) + } +} + +func TestSession_List(t *testing.T) { + c := makeClient(t) + session := c.Session() + + id, _, err := session.Create(nil, nil) + if err != nil { + t.Fatalf("err: %v", err) + } + defer session.Destroy(id, nil) + + sessions, qm, err := session.List(nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(sessions) != 1 { + t.Fatalf("bad: %v", sessions) + } + + if qm.LastIndex == 0 { + t.Fatalf("bad: %v", qm) + } + if !qm.KnownLeader { + t.Fatalf("bad: %v", qm) + } +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/status.go b/Godeps/_workspace/src/github.com/armon/consul-api/status.go new file mode 100644 index 00000000..21c31982 --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/status.go @@ -0,0 +1,43 @@ +package consulapi + +// Status can be used to query the Status endpoints +type Status struct { + c *Client +} + +// Status returns a handle to the status endpoints +func (c *Client) Status() *Status { + return &Status{c} +} + +// Leader is used to query for a known leader +func (s *Status) Leader() (string, error) { + r := s.c.newRequest("GET", "/v1/status/leader") + _, resp, err := requireOK(s.c.doRequest(r)) + if err != nil { + return "", err + } + defer resp.Body.Close() + + var leader string + if err := decodeBody(resp, &leader); err != nil { + return "", err + } + return leader, nil +} + +// Peers is used to query for a known raft peers +func (s *Status) Peers() ([]string, error) { + r := s.c.newRequest("GET", "/v1/status/peers") + _, resp, err := requireOK(s.c.doRequest(r)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var peers []string + if err := decodeBody(resp, &peers); err != nil { + return nil, err + } + return peers, nil +} diff --git a/Godeps/_workspace/src/github.com/armon/consul-api/status_test.go b/Godeps/_workspace/src/github.com/armon/consul-api/status_test.go new file mode 100644 index 00000000..ab9b42f5 --- /dev/null +++ b/Godeps/_workspace/src/github.com/armon/consul-api/status_test.go @@ -0,0 +1,31 @@ +package consulapi + +import ( + "testing" +) + +func TestStatusLeader(t *testing.T) { + c := makeClient(t) + status := c.Status() + + leader, err := status.Leader() + if err != nil { + t.Fatalf("err: %v", err) + } + if leader == "" { + t.Fatalf("Expected leader") + } +} + +func TestStatusPeers(t *testing.T) { + c := makeClient(t) + status := c.Status() + + peers, err := status.Peers() + if err != nil { + t.Fatalf("err: %v", err) + } + if len(peers) == 0 { + t.Fatalf("Expected peers ") + } +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/add_child.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/add_child.go new file mode 100644 index 00000000..7122be04 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/add_child.go @@ -0,0 +1,23 @@ +package etcd + +// Add a new directory with a random etcd-generated key under the given path. +func (c *Client) AddChildDir(key string, ttl uint64) (*Response, error) { + raw, err := c.post(key, "", ttl) + + if err != nil { + return nil, err + } + + return raw.Unmarshal() +} + +// Add a new file with a random etcd-generated key under the given path. +func (c *Client) AddChild(key string, value string, ttl uint64) (*Response, error) { + raw, err := c.post(key, value, ttl) + + if err != nil { + return nil, err + } + + return raw.Unmarshal() +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/add_child_test.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/add_child_test.go new file mode 100644 index 00000000..26223ff1 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/add_child_test.go @@ -0,0 +1,73 @@ +package etcd + +import "testing" + +func TestAddChild(t *testing.T) { + c := NewClient(nil) + defer func() { + c.Delete("fooDir", true) + c.Delete("nonexistentDir", true) + }() + + c.CreateDir("fooDir", 5) + + _, err := c.AddChild("fooDir", "v0", 5) + if err != nil { + t.Fatal(err) + } + + _, err = c.AddChild("fooDir", "v1", 5) + if err != nil { + t.Fatal(err) + } + + resp, err := c.Get("fooDir", true, false) + // The child with v0 should proceed the child with v1 because it's added + // earlier, so it should have a lower key. + if !(len(resp.Node.Nodes) == 2 && (resp.Node.Nodes[0].Value == "v0" && resp.Node.Nodes[1].Value == "v1")) { + t.Fatalf("AddChild 1 failed. There should be two chlidren whose values are v0 and v1, respectively."+ + " The response was: %#v", resp) + } + + // Creating a child under a nonexistent directory should succeed. + // The directory should be created. + resp, err = c.AddChild("nonexistentDir", "foo", 5) + if err != nil { + t.Fatal(err) + } +} + +func TestAddChildDir(t *testing.T) { + c := NewClient(nil) + defer func() { + c.Delete("fooDir", true) + c.Delete("nonexistentDir", true) + }() + + c.CreateDir("fooDir", 5) + + _, err := c.AddChildDir("fooDir", 5) + if err != nil { + t.Fatal(err) + } + + _, err = c.AddChildDir("fooDir", 5) + if err != nil { + t.Fatal(err) + } + + resp, err := c.Get("fooDir", true, false) + // The child with v0 should proceed the child with v1 because it's added + // earlier, so it should have a lower key. + if !(len(resp.Node.Nodes) == 2 && (len(resp.Node.Nodes[0].Nodes) == 0 && len(resp.Node.Nodes[1].Nodes) == 0)) { + t.Fatalf("AddChildDir 1 failed. There should be two chlidren whose values are v0 and v1, respectively."+ + " The response was: %#v", resp) + } + + // Creating a child under a nonexistent directory should succeed. + // The directory should be created. + resp, err = c.AddChildDir("nonexistentDir", 5) + if err != nil { + t.Fatal(err) + } +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/client.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/client.go new file mode 100644 index 00000000..c6cf3341 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/client.go @@ -0,0 +1,481 @@ +package etcd + +import ( + "crypto/tls" + "crypto/x509" + "encoding/json" + "errors" + "io" + "io/ioutil" + "math/rand" + "net" + "net/http" + "net/url" + "os" + "path" + "strings" + "time" +) + +// See SetConsistency for how to use these constants. +const ( + // Using strings rather than iota because the consistency level + // could be persisted to disk, so it'd be better to use + // human-readable values. + STRONG_CONSISTENCY = "STRONG" + WEAK_CONSISTENCY = "WEAK" +) + +const ( + defaultBufferSize = 10 +) + +func init() { + rand.Seed(int64(time.Now().Nanosecond())) +} + +type Config struct { + CertFile string `json:"certFile"` + KeyFile string `json:"keyFile"` + CaCertFile []string `json:"caCertFiles"` + DialTimeout time.Duration `json:"timeout"` + Consistency string `json:"consistency"` +} + +type credentials struct { + username string + password string +} + +type Client struct { + config Config `json:"config"` + cluster *Cluster `json:"cluster"` + httpClient *http.Client + credentials *credentials + transport *http.Transport + persistence io.Writer + cURLch chan string + // CheckRetry can be used to control the policy for failed requests + // and modify the cluster if needed. + // The client calls it before sending requests again, and + // stops retrying if CheckRetry returns some error. The cases that + // this function needs to handle include no response and unexpected + // http status code of response. + // If CheckRetry is nil, client will call the default one + // `DefaultCheckRetry`. + // Argument cluster is the etcd.Cluster object that these requests have been made on. + // Argument numReqs is the number of http.Requests that have been made so far. + // Argument lastResp is the http.Responses from the last request. + // Argument err is the reason of the failure. + CheckRetry func(cluster *Cluster, numReqs int, + lastResp http.Response, err error) error +} + +// NewClient create a basic client that is configured to be used +// with the given machine list. +func NewClient(machines []string) *Client { + config := Config{ + // default timeout is one second + DialTimeout: time.Second, + Consistency: WEAK_CONSISTENCY, + } + + client := &Client{ + cluster: NewCluster(machines), + config: config, + } + + client.initHTTPClient() + client.saveConfig() + + return client +} + +// NewTLSClient create a basic client with TLS configuration +func NewTLSClient(machines []string, cert, key, caCert string) (*Client, error) { + // overwrite the default machine to use https + if len(machines) == 0 { + machines = []string{"https://127.0.0.1:4001"} + } + + config := Config{ + // default timeout is one second + DialTimeout: time.Second, + Consistency: WEAK_CONSISTENCY, + CertFile: cert, + KeyFile: key, + CaCertFile: make([]string, 0), + } + + client := &Client{ + cluster: NewCluster(machines), + config: config, + } + + err := client.initHTTPSClient(cert, key) + if err != nil { + return nil, err + } + + err = client.AddRootCA(caCert) + + client.saveConfig() + + return client, nil +} + +// NewClientFromFile creates a client from a given file path. +// The given file is expected to use the JSON format. +func NewClientFromFile(fpath string) (*Client, error) { + fi, err := os.Open(fpath) + if err != nil { + return nil, err + } + + defer func() { + if err := fi.Close(); err != nil { + panic(err) + } + }() + + return NewClientFromReader(fi) +} + +// NewClientFromReader creates a Client configured from a given reader. +// The configuration is expected to use the JSON format. +func NewClientFromReader(reader io.Reader) (*Client, error) { + c := new(Client) + + b, err := ioutil.ReadAll(reader) + if err != nil { + return nil, err + } + + err = json.Unmarshal(b, c) + if err != nil { + return nil, err + } + if c.config.CertFile == "" { + c.initHTTPClient() + } else { + err = c.initHTTPSClient(c.config.CertFile, c.config.KeyFile) + } + + if err != nil { + return nil, err + } + + for _, caCert := range c.config.CaCertFile { + if err := c.AddRootCA(caCert); err != nil { + return nil, err + } + } + + return c, nil +} + +// Override the Client's HTTP Transport object +func (c *Client) SetTransport(tr *http.Transport) { + c.httpClient.Transport = tr + c.transport = tr +} + +func (c *Client) SetCredentials(username, password string) { + c.credentials = &credentials{username, password} +} + +func (c *Client) Close() { + c.transport.DisableKeepAlives = true + c.transport.CloseIdleConnections() +} + +// initHTTPClient initializes a HTTP client for etcd client +func (c *Client) initHTTPClient() { + c.transport = &http.Transport{ + Dial: c.dial, + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + } + c.httpClient = &http.Client{Transport: c.transport} +} + +// initHTTPClient initializes a HTTPS client for etcd client +func (c *Client) initHTTPSClient(cert, key string) error { + if cert == "" || key == "" { + return errors.New("Require both cert and key path") + } + + tlsCert, err := tls.LoadX509KeyPair(cert, key) + if err != nil { + return err + } + + tlsConfig := &tls.Config{ + Certificates: []tls.Certificate{tlsCert}, + InsecureSkipVerify: true, + } + + tr := &http.Transport{ + TLSClientConfig: tlsConfig, + Dial: c.dial, + } + + c.httpClient = &http.Client{Transport: tr} + return nil +} + +// SetPersistence sets a writer to which the config will be +// written every time it's changed. +func (c *Client) SetPersistence(writer io.Writer) { + c.persistence = writer +} + +// SetConsistency changes the consistency level of the client. +// +// When consistency is set to STRONG_CONSISTENCY, all requests, +// including GET, are sent to the leader. This means that, assuming +// the absence of leader failures, GET requests are guaranteed to see +// the changes made by previous requests. +// +// When consistency is set to WEAK_CONSISTENCY, other requests +// are still sent to the leader, but GET requests are sent to a +// random server from the server pool. This reduces the read +// load on the leader, but it's not guaranteed that the GET requests +// will see changes made by previous requests (they might have not +// yet been committed on non-leader servers). +func (c *Client) SetConsistency(consistency string) error { + if !(consistency == STRONG_CONSISTENCY || consistency == WEAK_CONSISTENCY) { + return errors.New("The argument must be either STRONG_CONSISTENCY or WEAK_CONSISTENCY.") + } + c.config.Consistency = consistency + return nil +} + +// Sets the DialTimeout value +func (c *Client) SetDialTimeout(d time.Duration) { + c.config.DialTimeout = d +} + +// AddRootCA adds a root CA cert for the etcd client +func (c *Client) AddRootCA(caCert string) error { + if c.httpClient == nil { + return errors.New("Client has not been initialized yet!") + } + + certBytes, err := ioutil.ReadFile(caCert) + if err != nil { + return err + } + + tr, ok := c.httpClient.Transport.(*http.Transport) + + if !ok { + panic("AddRootCA(): Transport type assert should not fail") + } + + if tr.TLSClientConfig.RootCAs == nil { + caCertPool := x509.NewCertPool() + ok = caCertPool.AppendCertsFromPEM(certBytes) + if ok { + tr.TLSClientConfig.RootCAs = caCertPool + } + tr.TLSClientConfig.InsecureSkipVerify = false + } else { + ok = tr.TLSClientConfig.RootCAs.AppendCertsFromPEM(certBytes) + } + + if !ok { + err = errors.New("Unable to load caCert") + } + + c.config.CaCertFile = append(c.config.CaCertFile, caCert) + c.saveConfig() + + return err +} + +// SetCluster updates cluster information using the given machine list. +func (c *Client) SetCluster(machines []string) bool { + success := c.internalSyncCluster(machines) + return success +} + +func (c *Client) GetCluster() []string { + return c.cluster.Machines +} + +// SyncCluster updates the cluster information using the internal machine list. +func (c *Client) SyncCluster() bool { + return c.internalSyncCluster(c.cluster.Machines) +} + +// internalSyncCluster syncs cluster information using the given machine list. +func (c *Client) internalSyncCluster(machines []string) bool { + for _, machine := range machines { + httpPath := c.createHttpPath(machine, path.Join(version, "members")) + resp, err := c.httpClient.Get(httpPath) + if err != nil { + // try another machine in the cluster + continue + } + + if resp.StatusCode != http.StatusOK { // fall-back to old endpoint + httpPath := c.createHttpPath(machine, path.Join(version, "machines")) + resp, err := c.httpClient.Get(httpPath) + if err != nil { + // try another machine in the cluster + continue + } + b, err := ioutil.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + // try another machine in the cluster + continue + } + // update Machines List + c.cluster.updateFromStr(string(b)) + } else { + b, err := ioutil.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + // try another machine in the cluster + continue + } + + var mCollection memberCollection + if err := json.Unmarshal(b, &mCollection); err != nil { + // try another machine + continue + } + + urls := make([]string, 0) + for _, m := range mCollection { + urls = append(urls, m.ClientURLs...) + } + + // update Machines List + c.cluster.updateFromStr(strings.Join(urls, ",")) + } + + logger.Debug("sync.machines ", c.cluster.Machines) + c.saveConfig() + return true + } + + return false +} + +// createHttpPath creates a complete HTTP URL. +// serverName should contain both the host name and a port number, if any. +func (c *Client) createHttpPath(serverName string, _path string) string { + u, err := url.Parse(serverName) + if err != nil { + panic(err) + } + + u.Path = path.Join(u.Path, _path) + + if u.Scheme == "" { + u.Scheme = "http" + } + return u.String() +} + +// dial attempts to open a TCP connection to the provided address, explicitly +// enabling keep-alives with a one-second interval. +func (c *Client) dial(network, addr string) (net.Conn, error) { + conn, err := net.DialTimeout(network, addr, c.config.DialTimeout) + if err != nil { + return nil, err + } + + tcpConn, ok := conn.(*net.TCPConn) + if !ok { + return nil, errors.New("Failed type-assertion of net.Conn as *net.TCPConn") + } + + // Keep TCP alive to check whether or not the remote machine is down + if err = tcpConn.SetKeepAlive(true); err != nil { + return nil, err + } + + if err = tcpConn.SetKeepAlivePeriod(time.Second); err != nil { + return nil, err + } + + return tcpConn, nil +} + +func (c *Client) OpenCURL() { + c.cURLch = make(chan string, defaultBufferSize) +} + +func (c *Client) CloseCURL() { + c.cURLch = nil +} + +func (c *Client) sendCURL(command string) { + go func() { + select { + case c.cURLch <- command: + default: + } + }() +} + +func (c *Client) RecvCURL() string { + return <-c.cURLch +} + +// saveConfig saves the current config using c.persistence. +func (c *Client) saveConfig() error { + if c.persistence != nil { + b, err := json.Marshal(c) + if err != nil { + return err + } + + _, err = c.persistence.Write(b) + if err != nil { + return err + } + } + + return nil +} + +// MarshalJSON implements the Marshaller interface +// as defined by the standard JSON package. +func (c *Client) MarshalJSON() ([]byte, error) { + b, err := json.Marshal(struct { + Config Config `json:"config"` + Cluster *Cluster `json:"cluster"` + }{ + Config: c.config, + Cluster: c.cluster, + }) + + if err != nil { + return nil, err + } + + return b, nil +} + +// UnmarshalJSON implements the Unmarshaller interface +// as defined by the standard JSON package. +func (c *Client) UnmarshalJSON(b []byte) error { + temp := struct { + Config Config `json:"config"` + Cluster *Cluster `json:"cluster"` + }{} + err := json.Unmarshal(b, &temp) + if err != nil { + return err + } + + c.cluster = temp.Cluster + c.config = temp.Config + return nil +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/client_test.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/client_test.go new file mode 100644 index 00000000..4720d8d6 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/client_test.go @@ -0,0 +1,108 @@ +package etcd + +import ( + "encoding/json" + "fmt" + "net" + "net/url" + "os" + "testing" +) + +// To pass this test, we need to create a cluster of 3 machines +// The server should be listening on localhost:4001, 4002, 4003 +func TestSync(t *testing.T) { + fmt.Println("Make sure there are three nodes at 0.0.0.0:4001-4003") + + // Explicit trailing slash to ensure this doesn't reproduce: + // https://github.com/coreos/go-etcd/issues/82 + c := NewClient([]string{"http://127.0.0.1:4001/"}) + + success := c.SyncCluster() + if !success { + t.Fatal("cannot sync machines") + } + + for _, m := range c.GetCluster() { + u, err := url.Parse(m) + if err != nil { + t.Fatal(err) + } + if u.Scheme != "http" { + t.Fatal("scheme must be http") + } + + host, _, err := net.SplitHostPort(u.Host) + if err != nil { + t.Fatal(err) + } + if host != "localhost" { + t.Fatal("Host must be localhost") + } + } + + badMachines := []string{"abc", "edef"} + + success = c.SetCluster(badMachines) + + if success { + t.Fatal("should not sync on bad machines") + } + + goodMachines := []string{"127.0.0.1:4002"} + + success = c.SetCluster(goodMachines) + + if !success { + t.Fatal("cannot sync machines") + } else { + fmt.Println(c.cluster.Machines) + } + +} + +func TestPersistence(t *testing.T) { + c := NewClient(nil) + c.SyncCluster() + + fo, err := os.Create("config.json") + if err != nil { + t.Fatal(err) + } + defer func() { + if err := fo.Close(); err != nil { + panic(err) + } + }() + + c.SetPersistence(fo) + err = c.saveConfig() + if err != nil { + t.Fatal(err) + } + + c2, err := NewClientFromFile("config.json") + if err != nil { + t.Fatal(err) + } + + // Verify that the two clients have the same config + b1, _ := json.Marshal(c) + b2, _ := json.Marshal(c2) + + if string(b1) != string(b2) { + t.Fatalf("The two configs should be equal!") + } +} + +func TestClientRetry(t *testing.T) { + c := NewClient([]string{"http://strange", "http://127.0.0.1:4001"}) + // use first endpoint as the picked url + c.cluster.picked = 0 + if _, err := c.Set("foo", "bar", 5); err != nil { + t.Fatal(err) + } + if _, err := c.Delete("foo", true); err != nil { + t.Fatal(err) + } +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/cluster.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/cluster.go new file mode 100644 index 00000000..1ad3e155 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/cluster.go @@ -0,0 +1,37 @@ +package etcd + +import ( + "math/rand" + "strings" +) + +type Cluster struct { + Leader string `json:"leader"` + Machines []string `json:"machines"` + picked int +} + +func NewCluster(machines []string) *Cluster { + // if an empty slice was sent in then just assume HTTP 4001 on localhost + if len(machines) == 0 { + machines = []string{"http://127.0.0.1:4001"} + } + + // default leader and machines + return &Cluster{ + Leader: "", + Machines: machines, + picked: rand.Intn(len(machines)), + } +} + +func (cl *Cluster) failure() { cl.picked = rand.Intn(len(cl.Machines)) } +func (cl *Cluster) pick() string { return cl.Machines[cl.picked] } + +func (cl *Cluster) updateFromStr(machines string) { + cl.Machines = strings.Split(machines, ",") + for i := range cl.Machines { + cl.Machines[i] = strings.TrimSpace(cl.Machines[i]) + } + cl.picked = rand.Intn(len(cl.Machines)) +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_delete.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_delete.go new file mode 100644 index 00000000..11131bb7 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_delete.go @@ -0,0 +1,34 @@ +package etcd + +import "fmt" + +func (c *Client) CompareAndDelete(key string, prevValue string, prevIndex uint64) (*Response, error) { + raw, err := c.RawCompareAndDelete(key, prevValue, prevIndex) + if err != nil { + return nil, err + } + + return raw.Unmarshal() +} + +func (c *Client) RawCompareAndDelete(key string, prevValue string, prevIndex uint64) (*RawResponse, error) { + if prevValue == "" && prevIndex == 0 { + return nil, fmt.Errorf("You must give either prevValue or prevIndex.") + } + + options := Options{} + if prevValue != "" { + options["prevValue"] = prevValue + } + if prevIndex != 0 { + options["prevIndex"] = prevIndex + } + + raw, err := c.delete(key, options) + + if err != nil { + return nil, err + } + + return raw, err +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_delete_test.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_delete_test.go new file mode 100644 index 00000000..223e50f2 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_delete_test.go @@ -0,0 +1,46 @@ +package etcd + +import ( + "testing" +) + +func TestCompareAndDelete(t *testing.T) { + c := NewClient(nil) + defer func() { + c.Delete("foo", true) + }() + + c.Set("foo", "bar", 5) + + // This should succeed an correct prevValue + resp, err := c.CompareAndDelete("foo", "bar", 0) + if err != nil { + t.Fatal(err) + } + if !(resp.PrevNode.Value == "bar" && resp.PrevNode.Key == "/foo" && resp.PrevNode.TTL == 5) { + t.Fatalf("CompareAndDelete 1 prevNode failed: %#v", resp) + } + + resp, _ = c.Set("foo", "bar", 5) + // This should fail because it gives an incorrect prevValue + _, err = c.CompareAndDelete("foo", "xxx", 0) + if err == nil { + t.Fatalf("CompareAndDelete 2 should have failed. The response is: %#v", resp) + } + + // This should succeed because it gives an correct prevIndex + resp, err = c.CompareAndDelete("foo", "", resp.Node.ModifiedIndex) + if err != nil { + t.Fatal(err) + } + if !(resp.PrevNode.Value == "bar" && resp.PrevNode.Key == "/foo" && resp.PrevNode.TTL == 5) { + t.Fatalf("CompareAndSwap 3 prevNode failed: %#v", resp) + } + + c.Set("foo", "bar", 5) + // This should fail because it gives an incorrect prevIndex + resp, err = c.CompareAndDelete("foo", "", 29817514) + if err == nil { + t.Fatalf("CompareAndDelete 4 should have failed. The response is: %#v", resp) + } +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_swap.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_swap.go new file mode 100644 index 00000000..bb4f9064 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_swap.go @@ -0,0 +1,36 @@ +package etcd + +import "fmt" + +func (c *Client) CompareAndSwap(key string, value string, ttl uint64, + prevValue string, prevIndex uint64) (*Response, error) { + raw, err := c.RawCompareAndSwap(key, value, ttl, prevValue, prevIndex) + if err != nil { + return nil, err + } + + return raw.Unmarshal() +} + +func (c *Client) RawCompareAndSwap(key string, value string, ttl uint64, + prevValue string, prevIndex uint64) (*RawResponse, error) { + if prevValue == "" && prevIndex == 0 { + return nil, fmt.Errorf("You must give either prevValue or prevIndex.") + } + + options := Options{} + if prevValue != "" { + options["prevValue"] = prevValue + } + if prevIndex != 0 { + options["prevIndex"] = prevIndex + } + + raw, err := c.put(key, value, ttl, options) + + if err != nil { + return nil, err + } + + return raw, err +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_swap_test.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_swap_test.go new file mode 100644 index 00000000..14a1b00f --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_swap_test.go @@ -0,0 +1,57 @@ +package etcd + +import ( + "testing" +) + +func TestCompareAndSwap(t *testing.T) { + c := NewClient(nil) + defer func() { + c.Delete("foo", true) + }() + + c.Set("foo", "bar", 5) + + // This should succeed + resp, err := c.CompareAndSwap("foo", "bar2", 5, "bar", 0) + if err != nil { + t.Fatal(err) + } + if !(resp.Node.Value == "bar2" && resp.Node.Key == "/foo" && resp.Node.TTL == 5) { + t.Fatalf("CompareAndSwap 1 failed: %#v", resp) + } + + if !(resp.PrevNode.Value == "bar" && resp.PrevNode.Key == "/foo" && resp.PrevNode.TTL == 5) { + t.Fatalf("CompareAndSwap 1 prevNode failed: %#v", resp) + } + + // This should fail because it gives an incorrect prevValue + resp, err = c.CompareAndSwap("foo", "bar3", 5, "xxx", 0) + if err == nil { + t.Fatalf("CompareAndSwap 2 should have failed. The response is: %#v", resp) + } + + resp, err = c.Set("foo", "bar", 5) + if err != nil { + t.Fatal(err) + } + + // This should succeed + resp, err = c.CompareAndSwap("foo", "bar2", 5, "", resp.Node.ModifiedIndex) + if err != nil { + t.Fatal(err) + } + if !(resp.Node.Value == "bar2" && resp.Node.Key == "/foo" && resp.Node.TTL == 5) { + t.Fatalf("CompareAndSwap 3 failed: %#v", resp) + } + + if !(resp.PrevNode.Value == "bar" && resp.PrevNode.Key == "/foo" && resp.PrevNode.TTL == 5) { + t.Fatalf("CompareAndSwap 3 prevNode failed: %#v", resp) + } + + // This should fail because it gives an incorrect prevIndex + resp, err = c.CompareAndSwap("foo", "bar3", 5, "", 29817514) + if err == nil { + t.Fatalf("CompareAndSwap 4 should have failed. The response is: %#v", resp) + } +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/debug.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/debug.go new file mode 100644 index 00000000..0f777886 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/debug.go @@ -0,0 +1,55 @@ +package etcd + +import ( + "fmt" + "io/ioutil" + "log" + "strings" +) + +var logger *etcdLogger + +func SetLogger(l *log.Logger) { + logger = &etcdLogger{l} +} + +func GetLogger() *log.Logger { + return logger.log +} + +type etcdLogger struct { + log *log.Logger +} + +func (p *etcdLogger) Debug(args ...interface{}) { + msg := "DEBUG: " + fmt.Sprint(args...) + p.log.Println(msg) +} + +func (p *etcdLogger) Debugf(f string, args ...interface{}) { + msg := "DEBUG: " + fmt.Sprintf(f, args...) + // Append newline if necessary + if !strings.HasSuffix(msg, "\n") { + msg = msg + "\n" + } + p.log.Print(msg) +} + +func (p *etcdLogger) Warning(args ...interface{}) { + msg := "WARNING: " + fmt.Sprint(args...) + p.log.Println(msg) +} + +func (p *etcdLogger) Warningf(f string, args ...interface{}) { + msg := "WARNING: " + fmt.Sprintf(f, args...) + // Append newline if necessary + if !strings.HasSuffix(msg, "\n") { + msg = msg + "\n" + } + p.log.Print(msg) +} + +func init() { + // Default logger uses the go default log. + SetLogger(log.New(ioutil.Discard, "go-etcd", log.LstdFlags)) +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/debug_test.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/debug_test.go new file mode 100644 index 00000000..97f6d111 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/debug_test.go @@ -0,0 +1,28 @@ +package etcd + +import ( + "testing" +) + +type Foo struct{} +type Bar struct { + one string + two int +} + +// Tests that logs don't panic with arbitrary interfaces +func TestDebug(t *testing.T) { + f := &Foo{} + b := &Bar{"asfd", 3} + for _, test := range []interface{}{ + 1234, + "asdf", + f, + b, + } { + logger.Debug(test) + logger.Debugf("something, %s", test) + logger.Warning(test) + logger.Warningf("something, %s", test) + } +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/delete.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/delete.go new file mode 100644 index 00000000..b37accd7 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/delete.go @@ -0,0 +1,40 @@ +package etcd + +// Delete deletes the given key. +// +// When recursive set to false, if the key points to a +// directory the method will fail. +// +// When recursive set to true, if the key points to a file, +// the file will be deleted; if the key points to a directory, +// then everything under the directory (including all child directories) +// will be deleted. +func (c *Client) Delete(key string, recursive bool) (*Response, error) { + raw, err := c.RawDelete(key, recursive, false) + + if err != nil { + return nil, err + } + + return raw.Unmarshal() +} + +// DeleteDir deletes an empty directory or a key value pair +func (c *Client) DeleteDir(key string) (*Response, error) { + raw, err := c.RawDelete(key, false, true) + + if err != nil { + return nil, err + } + + return raw.Unmarshal() +} + +func (c *Client) RawDelete(key string, recursive bool, dir bool) (*RawResponse, error) { + ops := Options{ + "recursive": recursive, + "dir": dir, + } + + return c.delete(key, ops) +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/delete_test.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/delete_test.go new file mode 100644 index 00000000..59049715 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/delete_test.go @@ -0,0 +1,81 @@ +package etcd + +import ( + "testing" +) + +func TestDelete(t *testing.T) { + c := NewClient(nil) + defer func() { + c.Delete("foo", true) + }() + + c.Set("foo", "bar", 5) + resp, err := c.Delete("foo", false) + if err != nil { + t.Fatal(err) + } + + if !(resp.Node.Value == "") { + t.Fatalf("Delete failed with %s", resp.Node.Value) + } + + if !(resp.PrevNode.Value == "bar") { + t.Fatalf("Delete PrevNode failed with %s", resp.Node.Value) + } + + resp, err = c.Delete("foo", false) + if err == nil { + t.Fatalf("Delete should have failed because the key foo did not exist. "+ + "The response was: %v", resp) + } +} + +func TestDeleteAll(t *testing.T) { + c := NewClient(nil) + defer func() { + c.Delete("foo", true) + c.Delete("fooDir", true) + }() + + c.SetDir("foo", 5) + // test delete an empty dir + resp, err := c.DeleteDir("foo") + if err != nil { + t.Fatal(err) + } + + if !(resp.Node.Value == "") { + t.Fatalf("DeleteAll 1 failed: %#v", resp) + } + + if !(resp.PrevNode.Dir == true && resp.PrevNode.Value == "") { + t.Fatalf("DeleteAll 1 PrevNode failed: %#v", resp) + } + + c.CreateDir("fooDir", 5) + c.Set("fooDir/foo", "bar", 5) + _, err = c.DeleteDir("fooDir") + if err == nil { + t.Fatal("should not able to delete a non-empty dir with deletedir") + } + + resp, err = c.Delete("fooDir", true) + if err != nil { + t.Fatal(err) + } + + if !(resp.Node.Value == "") { + t.Fatalf("DeleteAll 2 failed: %#v", resp) + } + + if !(resp.PrevNode.Dir == true && resp.PrevNode.Value == "") { + t.Fatalf("DeleteAll 2 PrevNode failed: %#v", resp) + } + + resp, err = c.Delete("foo", true) + if err == nil { + t.Fatalf("DeleteAll should have failed because the key foo did not exist. "+ + "The response was: %v", resp) + } +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/error.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/error.go new file mode 100644 index 00000000..66dca54b --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/error.go @@ -0,0 +1,49 @@ +package etcd + +import ( + "encoding/json" + "fmt" +) + +const ( + ErrCodeEtcdNotReachable = 501 + ErrCodeUnhandledHTTPStatus = 502 +) + +var ( + errorMap = map[int]string{ + ErrCodeEtcdNotReachable: "All the given peers are not reachable", + } +) + +type EtcdError struct { + ErrorCode int `json:"errorCode"` + Message string `json:"message"` + Cause string `json:"cause,omitempty"` + Index uint64 `json:"index"` +} + +func (e EtcdError) Error() string { + return fmt.Sprintf("%v: %v (%v) [%v]", e.ErrorCode, e.Message, e.Cause, e.Index) +} + +func newError(errorCode int, cause string, index uint64) *EtcdError { + return &EtcdError{ + ErrorCode: errorCode, + Message: errorMap[errorCode], + Cause: cause, + Index: index, + } +} + +func handleError(b []byte) error { + etcdErr := new(EtcdError) + + err := json.Unmarshal(b, etcdErr) + if err != nil { + logger.Warningf("cannot unmarshal etcd error: %v", err) + return err + } + + return etcdErr +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/get.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/get.go new file mode 100644 index 00000000..09fe641c --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/get.go @@ -0,0 +1,32 @@ +package etcd + +// Get gets the file or directory associated with the given key. +// If the key points to a directory, files and directories under +// it will be returned in sorted or unsorted order, depending on +// the sort flag. +// If recursive is set to false, contents under child directories +// will not be returned. +// If recursive is set to true, all the contents will be returned. +func (c *Client) Get(key string, sort, recursive bool) (*Response, error) { + raw, err := c.RawGet(key, sort, recursive) + + if err != nil { + return nil, err + } + + return raw.Unmarshal() +} + +func (c *Client) RawGet(key string, sort, recursive bool) (*RawResponse, error) { + var q bool + if c.config.Consistency == STRONG_CONSISTENCY { + q = true + } + ops := Options{ + "recursive": recursive, + "sorted": sort, + "quorum": q, + } + + return c.get(key, ops) +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/get_test.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/get_test.go new file mode 100644 index 00000000..279c4e26 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/get_test.go @@ -0,0 +1,131 @@ +package etcd + +import ( + "reflect" + "testing" +) + +// cleanNode scrubs Expiration, ModifiedIndex and CreatedIndex of a node. +func cleanNode(n *Node) { + n.Expiration = nil + n.ModifiedIndex = 0 + n.CreatedIndex = 0 +} + +// cleanResult scrubs a result object two levels deep of Expiration, +// ModifiedIndex and CreatedIndex. +func cleanResult(result *Response) { + // TODO(philips): make this recursive. + cleanNode(result.Node) + for i, _ := range result.Node.Nodes { + cleanNode(result.Node.Nodes[i]) + for j, _ := range result.Node.Nodes[i].Nodes { + cleanNode(result.Node.Nodes[i].Nodes[j]) + } + } +} + +func TestGet(t *testing.T) { + c := NewClient(nil) + defer func() { + c.Delete("foo", true) + }() + + c.Set("foo", "bar", 5) + + result, err := c.Get("foo", false, false) + + if err != nil { + t.Fatal(err) + } + + if result.Node.Key != "/foo" || result.Node.Value != "bar" { + t.Fatalf("Get failed with %s %s %v", result.Node.Key, result.Node.Value, result.Node.TTL) + } + + result, err = c.Get("goo", false, false) + if err == nil { + t.Fatalf("should not be able to get non-exist key") + } +} + +func TestGetAll(t *testing.T) { + c := NewClient(nil) + defer func() { + c.Delete("fooDir", true) + }() + + c.CreateDir("fooDir", 5) + c.Set("fooDir/k0", "v0", 5) + c.Set("fooDir/k1", "v1", 5) + + // Return kv-pairs in sorted order + result, err := c.Get("fooDir", true, false) + + if err != nil { + t.Fatal(err) + } + + expected := Nodes{ + &Node{ + Key: "/fooDir/k0", + Value: "v0", + TTL: 5, + }, + &Node{ + Key: "/fooDir/k1", + Value: "v1", + TTL: 5, + }, + } + + cleanResult(result) + + if !reflect.DeepEqual(result.Node.Nodes, expected) { + t.Fatalf("(actual) %v != (expected) %v", result.Node.Nodes, expected) + } + + // Test the `recursive` option + c.CreateDir("fooDir/childDir", 5) + c.Set("fooDir/childDir/k2", "v2", 5) + + // Return kv-pairs in sorted order + result, err = c.Get("fooDir", true, true) + + cleanResult(result) + + if err != nil { + t.Fatal(err) + } + + expected = Nodes{ + &Node{ + Key: "/fooDir/childDir", + Dir: true, + Nodes: Nodes{ + &Node{ + Key: "/fooDir/childDir/k2", + Value: "v2", + TTL: 5, + }, + }, + TTL: 5, + }, + &Node{ + Key: "/fooDir/k0", + Value: "v0", + TTL: 5, + }, + &Node{ + Key: "/fooDir/k1", + Value: "v1", + TTL: 5, + }, + } + + cleanResult(result) + + if !reflect.DeepEqual(result.Node.Nodes, expected) { + t.Fatalf("(actual) %v != (expected) %v", result.Node.Nodes, expected) + } +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/member.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/member.go new file mode 100644 index 00000000..5b13b28e --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/member.go @@ -0,0 +1,30 @@ +package etcd + +import "encoding/json" + +type Member struct { + ID string `json:"id"` + Name string `json:"name"` + PeerURLs []string `json:"peerURLs"` + ClientURLs []string `json:"clientURLs"` +} + +type memberCollection []Member + +func (c *memberCollection) UnmarshalJSON(data []byte) error { + d := struct { + Members []Member + }{} + + if err := json.Unmarshal(data, &d); err != nil { + return err + } + + if d.Members == nil { + *c = make([]Member, 0) + return nil + } + + *c = d.Members + return nil +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/member_test.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/member_test.go new file mode 100644 index 00000000..53ebdd4b --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/member_test.go @@ -0,0 +1,71 @@ +package etcd + +import ( + "encoding/json" + "reflect" + "testing" +) + +func TestMemberCollectionUnmarshal(t *testing.T) { + tests := []struct { + body []byte + want memberCollection + }{ + { + body: []byte(`{"members":[]}`), + want: memberCollection([]Member{}), + }, + { + body: []byte(`{"members":[{"id":"2745e2525fce8fe","peerURLs":["http://127.0.0.1:7003"],"name":"node3","clientURLs":["http://127.0.0.1:4003"]},{"id":"42134f434382925","peerURLs":["http://127.0.0.1:2380","http://127.0.0.1:7001"],"name":"node1","clientURLs":["http://127.0.0.1:2379","http://127.0.0.1:4001"]},{"id":"94088180e21eb87b","peerURLs":["http://127.0.0.1:7002"],"name":"node2","clientURLs":["http://127.0.0.1:4002"]}]}`), + want: memberCollection( + []Member{ + { + ID: "2745e2525fce8fe", + Name: "node3", + PeerURLs: []string{ + "http://127.0.0.1:7003", + }, + ClientURLs: []string{ + "http://127.0.0.1:4003", + }, + }, + { + ID: "42134f434382925", + Name: "node1", + PeerURLs: []string{ + "http://127.0.0.1:2380", + "http://127.0.0.1:7001", + }, + ClientURLs: []string{ + "http://127.0.0.1:2379", + "http://127.0.0.1:4001", + }, + }, + { + ID: "94088180e21eb87b", + Name: "node2", + PeerURLs: []string{ + "http://127.0.0.1:7002", + }, + ClientURLs: []string{ + "http://127.0.0.1:4002", + }, + }, + }, + ), + }, + } + + for i, tt := range tests { + var got memberCollection + err := json.Unmarshal(tt.body, &got) + if err != nil { + t.Errorf("#%d: unexpected error: %v", i, err) + continue + } + + if !reflect.DeepEqual(tt.want, got) { + t.Errorf("#%d: incorrect output: want=%#v, got=%#v", i, tt.want, got) + } + } +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/options.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/options.go new file mode 100644 index 00000000..d21c96f0 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/options.go @@ -0,0 +1,72 @@ +package etcd + +import ( + "fmt" + "net/url" + "reflect" +) + +type Options map[string]interface{} + +// An internally-used data structure that represents a mapping +// between valid options and their kinds +type validOptions map[string]reflect.Kind + +// Valid options for GET, PUT, POST, DELETE +// Using CAPITALIZED_UNDERSCORE to emphasize that these +// values are meant to be used as constants. +var ( + VALID_GET_OPTIONS = validOptions{ + "recursive": reflect.Bool, + "quorum": reflect.Bool, + "sorted": reflect.Bool, + "wait": reflect.Bool, + "waitIndex": reflect.Uint64, + } + + VALID_PUT_OPTIONS = validOptions{ + "prevValue": reflect.String, + "prevIndex": reflect.Uint64, + "prevExist": reflect.Bool, + "dir": reflect.Bool, + } + + VALID_POST_OPTIONS = validOptions{} + + VALID_DELETE_OPTIONS = validOptions{ + "recursive": reflect.Bool, + "dir": reflect.Bool, + "prevValue": reflect.String, + "prevIndex": reflect.Uint64, + } +) + +// Convert options to a string of HTML parameters +func (ops Options) toParameters(validOps validOptions) (string, error) { + p := "?" + values := url.Values{} + + if ops == nil { + return "", nil + } + + for k, v := range ops { + // Check if the given option is valid (that it exists) + kind := validOps[k] + if kind == reflect.Invalid { + return "", fmt.Errorf("Invalid option: %v", k) + } + + // Check if the given option is of the valid type + t := reflect.TypeOf(v) + if kind != t.Kind() { + return "", fmt.Errorf("Option %s should be of %v kind, not of %v kind.", + k, kind, t.Kind()) + } + + values.Set(k, fmt.Sprintf("%v", v)) + } + + p += values.Encode() + return p, nil +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/requests.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/requests.go new file mode 100644 index 00000000..3c3f436b --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/requests.go @@ -0,0 +1,403 @@ +package etcd + +import ( + "errors" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "path" + "strings" + "sync" + "time" +) + +// Errors introduced by handling requests +var ( + ErrRequestCancelled = errors.New("sending request is cancelled") +) + +type RawRequest struct { + Method string + RelativePath string + Values url.Values + Cancel <-chan bool +} + +// NewRawRequest returns a new RawRequest +func NewRawRequest(method, relativePath string, values url.Values, cancel <-chan bool) *RawRequest { + return &RawRequest{ + Method: method, + RelativePath: relativePath, + Values: values, + Cancel: cancel, + } +} + +// getCancelable issues a cancelable GET request +func (c *Client) getCancelable(key string, options Options, + cancel <-chan bool) (*RawResponse, error) { + logger.Debugf("get %s [%s]", key, c.cluster.pick()) + p := keyToPath(key) + + str, err := options.toParameters(VALID_GET_OPTIONS) + if err != nil { + return nil, err + } + p += str + + req := NewRawRequest("GET", p, nil, cancel) + resp, err := c.SendRequest(req) + + if err != nil { + return nil, err + } + + return resp, nil +} + +// get issues a GET request +func (c *Client) get(key string, options Options) (*RawResponse, error) { + return c.getCancelable(key, options, nil) +} + +// put issues a PUT request +func (c *Client) put(key string, value string, ttl uint64, + options Options) (*RawResponse, error) { + + logger.Debugf("put %s, %s, ttl: %d, [%s]", key, value, ttl, c.cluster.pick()) + p := keyToPath(key) + + str, err := options.toParameters(VALID_PUT_OPTIONS) + if err != nil { + return nil, err + } + p += str + + req := NewRawRequest("PUT", p, buildValues(value, ttl), nil) + resp, err := c.SendRequest(req) + + if err != nil { + return nil, err + } + + return resp, nil +} + +// post issues a POST request +func (c *Client) post(key string, value string, ttl uint64) (*RawResponse, error) { + logger.Debugf("post %s, %s, ttl: %d, [%s]", key, value, ttl, c.cluster.pick()) + p := keyToPath(key) + + req := NewRawRequest("POST", p, buildValues(value, ttl), nil) + resp, err := c.SendRequest(req) + + if err != nil { + return nil, err + } + + return resp, nil +} + +// delete issues a DELETE request +func (c *Client) delete(key string, options Options) (*RawResponse, error) { + logger.Debugf("delete %s [%s]", key, c.cluster.pick()) + p := keyToPath(key) + + str, err := options.toParameters(VALID_DELETE_OPTIONS) + if err != nil { + return nil, err + } + p += str + + req := NewRawRequest("DELETE", p, nil, nil) + resp, err := c.SendRequest(req) + + if err != nil { + return nil, err + } + + return resp, nil +} + +// SendRequest sends a HTTP request and returns a Response as defined by etcd +func (c *Client) SendRequest(rr *RawRequest) (*RawResponse, error) { + var req *http.Request + var resp *http.Response + var httpPath string + var err error + var respBody []byte + + var numReqs = 1 + + checkRetry := c.CheckRetry + if checkRetry == nil { + checkRetry = DefaultCheckRetry + } + + cancelled := make(chan bool, 1) + reqLock := new(sync.Mutex) + + if rr.Cancel != nil { + cancelRoutine := make(chan bool) + defer close(cancelRoutine) + + go func() { + select { + case <-rr.Cancel: + cancelled <- true + logger.Debug("send.request is cancelled") + case <-cancelRoutine: + return + } + + // Repeat canceling request until this thread is stopped + // because we have no idea about whether it succeeds. + for { + reqLock.Lock() + c.httpClient.Transport.(*http.Transport).CancelRequest(req) + reqLock.Unlock() + + select { + case <-time.After(100 * time.Millisecond): + case <-cancelRoutine: + return + } + } + }() + } + + // If we connect to a follower and consistency is required, retry until + // we connect to a leader + sleep := 25 * time.Millisecond + maxSleep := time.Second + + for attempt := 0; ; attempt++ { + if attempt > 0 { + select { + case <-cancelled: + return nil, ErrRequestCancelled + case <-time.After(sleep): + sleep = sleep * 2 + if sleep > maxSleep { + sleep = maxSleep + } + } + } + + logger.Debug("Connecting to etcd: attempt ", attempt+1, " for ", rr.RelativePath) + + // get httpPath if not set + if httpPath == "" { + httpPath = c.getHttpPath(rr.RelativePath) + } + + // Return a cURL command if curlChan is set + if c.cURLch != nil { + command := fmt.Sprintf("curl -X %s %s", rr.Method, httpPath) + for key, value := range rr.Values { + command += fmt.Sprintf(" -d %s=%s", key, value[0]) + } + if c.credentials != nil { + command += fmt.Sprintf(" -u %s", c.credentials.username) + } + c.sendCURL(command) + } + + logger.Debug("send.request.to ", httpPath, " | method ", rr.Method) + + req, err := func() (*http.Request, error) { + reqLock.Lock() + defer reqLock.Unlock() + + if rr.Values == nil { + if req, err = http.NewRequest(rr.Method, httpPath, nil); err != nil { + return nil, err + } + } else { + body := strings.NewReader(rr.Values.Encode()) + if req, err = http.NewRequest(rr.Method, httpPath, body); err != nil { + return nil, err + } + + req.Header.Set("Content-Type", + "application/x-www-form-urlencoded; param=value") + } + return req, nil + }() + + if err != nil { + return nil, err + } + + if c.credentials != nil { + req.SetBasicAuth(c.credentials.username, c.credentials.password) + } + + resp, err = c.httpClient.Do(req) + // clear previous httpPath + httpPath = "" + defer func() { + if resp != nil { + resp.Body.Close() + } + }() + + // If the request was cancelled, return ErrRequestCancelled directly + select { + case <-cancelled: + return nil, ErrRequestCancelled + default: + } + + numReqs++ + + // network error, change a machine! + if err != nil { + logger.Debug("network error: ", err.Error()) + lastResp := http.Response{} + if checkErr := checkRetry(c.cluster, numReqs, lastResp, err); checkErr != nil { + return nil, checkErr + } + + c.cluster.failure() + continue + } + + // if there is no error, it should receive response + logger.Debug("recv.response.from ", httpPath) + + if validHttpStatusCode[resp.StatusCode] { + // try to read byte code and break the loop + respBody, err = ioutil.ReadAll(resp.Body) + if err == nil { + logger.Debug("recv.success ", httpPath) + break + } + // ReadAll error may be caused due to cancel request + select { + case <-cancelled: + return nil, ErrRequestCancelled + default: + } + + if err == io.ErrUnexpectedEOF { + // underlying connection was closed prematurely, probably by timeout + // TODO: empty body or unexpectedEOF can cause http.Transport to get hosed; + // this allows the client to detect that and take evasive action. Need + // to revisit once code.google.com/p/go/issues/detail?id=8648 gets fixed. + respBody = []byte{} + break + } + } + + if resp.StatusCode == http.StatusTemporaryRedirect { + u, err := resp.Location() + + if err != nil { + logger.Warning(err) + } else { + // set httpPath for following redirection + httpPath = u.String() + } + resp.Body.Close() + continue + } + + if checkErr := checkRetry(c.cluster, numReqs, *resp, + errors.New("Unexpected HTTP status code")); checkErr != nil { + return nil, checkErr + } + resp.Body.Close() + } + + r := &RawResponse{ + StatusCode: resp.StatusCode, + Body: respBody, + Header: resp.Header, + } + + return r, nil +} + +// DefaultCheckRetry defines the retrying behaviour for bad HTTP requests +// If we have retried 2 * machine number, stop retrying. +// If status code is InternalServerError, sleep for 200ms. +func DefaultCheckRetry(cluster *Cluster, numReqs int, lastResp http.Response, + err error) error { + + if numReqs > 2*len(cluster.Machines) { + errStr := fmt.Sprintf("failed to propose on members %v twice [last error: %v]", cluster.Machines, err) + return newError(ErrCodeEtcdNotReachable, errStr, 0) + } + + if isEmptyResponse(lastResp) { + // always retry if it failed to get response from one machine + return nil + } + if !shouldRetry(lastResp) { + body := []byte("nil") + if lastResp.Body != nil { + if b, err := ioutil.ReadAll(lastResp.Body); err == nil { + body = b + } + } + errStr := fmt.Sprintf("unhandled http status [%s] with body [%s]", http.StatusText(lastResp.StatusCode), body) + return newError(ErrCodeUnhandledHTTPStatus, errStr, 0) + } + // sleep some time and expect leader election finish + time.Sleep(time.Millisecond * 200) + logger.Warning("bad response status code", lastResp.StatusCode) + return nil +} + +func isEmptyResponse(r http.Response) bool { return r.StatusCode == 0 } + +// shouldRetry returns whether the reponse deserves retry. +func shouldRetry(r http.Response) bool { + // TODO: only retry when the cluster is in leader election + // We cannot do it exactly because etcd doesn't support it well. + return r.StatusCode == http.StatusInternalServerError +} + +func (c *Client) getHttpPath(s ...string) string { + fullPath := c.cluster.pick() + "/" + version + for _, seg := range s { + fullPath = fullPath + "/" + seg + } + return fullPath +} + +// buildValues builds a url.Values map according to the given value and ttl +func buildValues(value string, ttl uint64) url.Values { + v := url.Values{} + + if value != "" { + v.Set("value", value) + } + + if ttl > 0 { + v.Set("ttl", fmt.Sprintf("%v", ttl)) + } + + return v +} + +// convert key string to http path exclude version, including URL escaping +// for example: key[foo] -> path[keys/foo] +// key[/%z] -> path[keys/%25z] +// key[/] -> path[keys/] +func keyToPath(key string) string { + // URL-escape our key, except for slashes + p := strings.Replace(url.QueryEscape(path.Join("keys", key)), "%2F", "/", -1) + + // corner case: if key is "/" or "//" ect + // path join will clear the tailing "/" + // we need to add it back + if p == "keys" { + p = "keys/" + } + + return p +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/requests_test.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/requests_test.go new file mode 100644 index 00000000..7a2bd190 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/requests_test.go @@ -0,0 +1,22 @@ +package etcd + +import "testing" + +func TestKeyToPath(t *testing.T) { + tests := []struct { + key string + wpath string + }{ + {"", "keys/"}, + {"foo", "keys/foo"}, + {"foo/bar", "keys/foo/bar"}, + {"%z", "keys/%25z"}, + {"/", "keys/"}, + } + for i, tt := range tests { + path := keyToPath(tt.key) + if path != tt.wpath { + t.Errorf("#%d: path = %s, want %s", i, path, tt.wpath) + } + } +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/response.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/response.go new file mode 100644 index 00000000..1fe9b4e8 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/response.go @@ -0,0 +1,89 @@ +package etcd + +import ( + "encoding/json" + "net/http" + "strconv" + "time" +) + +const ( + rawResponse = iota + normalResponse +) + +type responseType int + +type RawResponse struct { + StatusCode int + Body []byte + Header http.Header +} + +var ( + validHttpStatusCode = map[int]bool{ + http.StatusCreated: true, + http.StatusOK: true, + http.StatusBadRequest: true, + http.StatusNotFound: true, + http.StatusPreconditionFailed: true, + http.StatusForbidden: true, + } +) + +// Unmarshal parses RawResponse and stores the result in Response +func (rr *RawResponse) Unmarshal() (*Response, error) { + if rr.StatusCode != http.StatusOK && rr.StatusCode != http.StatusCreated { + return nil, handleError(rr.Body) + } + + resp := new(Response) + + err := json.Unmarshal(rr.Body, resp) + + if err != nil { + return nil, err + } + + // attach index and term to response + resp.EtcdIndex, _ = strconv.ParseUint(rr.Header.Get("X-Etcd-Index"), 10, 64) + resp.RaftIndex, _ = strconv.ParseUint(rr.Header.Get("X-Raft-Index"), 10, 64) + resp.RaftTerm, _ = strconv.ParseUint(rr.Header.Get("X-Raft-Term"), 10, 64) + + return resp, nil +} + +type Response struct { + Action string `json:"action"` + Node *Node `json:"node"` + PrevNode *Node `json:"prevNode,omitempty"` + EtcdIndex uint64 `json:"etcdIndex"` + RaftIndex uint64 `json:"raftIndex"` + RaftTerm uint64 `json:"raftTerm"` +} + +type Node struct { + Key string `json:"key, omitempty"` + Value string `json:"value,omitempty"` + Dir bool `json:"dir,omitempty"` + Expiration *time.Time `json:"expiration,omitempty"` + TTL int64 `json:"ttl,omitempty"` + Nodes Nodes `json:"nodes,omitempty"` + ModifiedIndex uint64 `json:"modifiedIndex,omitempty"` + CreatedIndex uint64 `json:"createdIndex,omitempty"` +} + +type Nodes []*Node + +// interfaces for sorting +func (ns Nodes) Len() int { + return len(ns) +} + +func (ns Nodes) Less(i, j int) bool { + return ns[i].Key < ns[j].Key +} + +func (ns Nodes) Swap(i, j int) { + ns[i], ns[j] = ns[j], ns[i] +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/set_curl_chan_test.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/set_curl_chan_test.go new file mode 100644 index 00000000..87c86b83 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/set_curl_chan_test.go @@ -0,0 +1,42 @@ +package etcd + +import ( + "fmt" + "testing" +) + +func TestSetCurlChan(t *testing.T) { + c := NewClient(nil) + c.OpenCURL() + + defer func() { + c.Delete("foo", true) + }() + + _, err := c.Set("foo", "bar", 5) + if err != nil { + t.Fatal(err) + } + + expected := fmt.Sprintf("curl -X PUT %s/v2/keys/foo -d value=bar -d ttl=5", + c.cluster.pick()) + actual := c.RecvCURL() + if expected != actual { + t.Fatalf(`Command "%s" is not equal to expected value "%s"`, + actual, expected) + } + + c.SetConsistency(STRONG_CONSISTENCY) + _, err = c.Get("foo", false, false) + if err != nil { + t.Fatal(err) + } + + expected = fmt.Sprintf("curl -X GET %s/v2/keys/foo?quorum=true&recursive=false&sorted=false", + c.cluster.pick()) + actual = c.RecvCURL() + if expected != actual { + t.Fatalf(`Command "%s" is not equal to expected value "%s"`, + actual, expected) + } +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/set_update_create.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/set_update_create.go new file mode 100644 index 00000000..e2840cf3 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/set_update_create.go @@ -0,0 +1,137 @@ +package etcd + +// Set sets the given key to the given value. +// It will create a new key value pair or replace the old one. +// It will not replace a existing directory. +func (c *Client) Set(key string, value string, ttl uint64) (*Response, error) { + raw, err := c.RawSet(key, value, ttl) + + if err != nil { + return nil, err + } + + return raw.Unmarshal() +} + +// SetDir sets the given key to a directory. +// It will create a new directory or replace the old key value pair by a directory. +// It will not replace a existing directory. +func (c *Client) SetDir(key string, ttl uint64) (*Response, error) { + raw, err := c.RawSetDir(key, ttl) + + if err != nil { + return nil, err + } + + return raw.Unmarshal() +} + +// CreateDir creates a directory. It succeeds only if +// the given key does not yet exist. +func (c *Client) CreateDir(key string, ttl uint64) (*Response, error) { + raw, err := c.RawCreateDir(key, ttl) + + if err != nil { + return nil, err + } + + return raw.Unmarshal() +} + +// UpdateDir updates the given directory. It succeeds only if the +// given key already exists. +func (c *Client) UpdateDir(key string, ttl uint64) (*Response, error) { + raw, err := c.RawUpdateDir(key, ttl) + + if err != nil { + return nil, err + } + + return raw.Unmarshal() +} + +// Create creates a file with the given value under the given key. It succeeds +// only if the given key does not yet exist. +func (c *Client) Create(key string, value string, ttl uint64) (*Response, error) { + raw, err := c.RawCreate(key, value, ttl) + + if err != nil { + return nil, err + } + + return raw.Unmarshal() +} + +// CreateInOrder creates a file with a key that's guaranteed to be higher than other +// keys in the given directory. It is useful for creating queues. +func (c *Client) CreateInOrder(dir string, value string, ttl uint64) (*Response, error) { + raw, err := c.RawCreateInOrder(dir, value, ttl) + + if err != nil { + return nil, err + } + + return raw.Unmarshal() +} + +// Update updates the given key to the given value. It succeeds only if the +// given key already exists. +func (c *Client) Update(key string, value string, ttl uint64) (*Response, error) { + raw, err := c.RawUpdate(key, value, ttl) + + if err != nil { + return nil, err + } + + return raw.Unmarshal() +} + +func (c *Client) RawUpdateDir(key string, ttl uint64) (*RawResponse, error) { + ops := Options{ + "prevExist": true, + "dir": true, + } + + return c.put(key, "", ttl, ops) +} + +func (c *Client) RawCreateDir(key string, ttl uint64) (*RawResponse, error) { + ops := Options{ + "prevExist": false, + "dir": true, + } + + return c.put(key, "", ttl, ops) +} + +func (c *Client) RawSet(key string, value string, ttl uint64) (*RawResponse, error) { + return c.put(key, value, ttl, nil) +} + +func (c *Client) RawSetDir(key string, ttl uint64) (*RawResponse, error) { + ops := Options{ + "dir": true, + } + + return c.put(key, "", ttl, ops) +} + +func (c *Client) RawUpdate(key string, value string, ttl uint64) (*RawResponse, error) { + ops := Options{ + "prevExist": true, + } + + return c.put(key, value, ttl, ops) +} + +func (c *Client) RawCreate(key string, value string, ttl uint64) (*RawResponse, error) { + ops := Options{ + "prevExist": false, + } + + return c.put(key, value, ttl, ops) +} + +func (c *Client) RawCreateInOrder(dir string, value string, ttl uint64) (*RawResponse, error) { + return c.post(dir, value, ttl) +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/set_update_create_test.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/set_update_create_test.go new file mode 100644 index 00000000..ced0f06e --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/set_update_create_test.go @@ -0,0 +1,241 @@ +package etcd + +import ( + "testing" +) + +func TestSet(t *testing.T) { + c := NewClient(nil) + defer func() { + c.Delete("foo", true) + }() + + resp, err := c.Set("foo", "bar", 5) + if err != nil { + t.Fatal(err) + } + if resp.Node.Key != "/foo" || resp.Node.Value != "bar" || resp.Node.TTL != 5 { + t.Fatalf("Set 1 failed: %#v", resp) + } + if resp.PrevNode != nil { + t.Fatalf("Set 1 PrevNode failed: %#v", resp) + } + + resp, err = c.Set("foo", "bar2", 5) + if err != nil { + t.Fatal(err) + } + if !(resp.Node.Key == "/foo" && resp.Node.Value == "bar2" && resp.Node.TTL == 5) { + t.Fatalf("Set 2 failed: %#v", resp) + } + if resp.PrevNode.Key != "/foo" || resp.PrevNode.Value != "bar" || resp.Node.TTL != 5 { + t.Fatalf("Set 2 PrevNode failed: %#v", resp) + } +} + +func TestUpdate(t *testing.T) { + c := NewClient(nil) + defer func() { + c.Delete("foo", true) + c.Delete("nonexistent", true) + }() + + resp, err := c.Set("foo", "bar", 5) + + if err != nil { + t.Fatal(err) + } + + // This should succeed. + resp, err = c.Update("foo", "wakawaka", 5) + if err != nil { + t.Fatal(err) + } + + if !(resp.Action == "update" && resp.Node.Key == "/foo" && resp.Node.TTL == 5) { + t.Fatalf("Update 1 failed: %#v", resp) + } + if !(resp.PrevNode.Key == "/foo" && resp.PrevNode.Value == "bar" && resp.Node.TTL == 5) { + t.Fatalf("Update 1 prevValue failed: %#v", resp) + } + + // This should fail because the key does not exist. + resp, err = c.Update("nonexistent", "whatever", 5) + if err == nil { + t.Fatalf("The key %v did not exist, so the update should have failed."+ + "The response was: %#v", resp.Node.Key, resp) + } +} + +func TestCreate(t *testing.T) { + c := NewClient(nil) + defer func() { + c.Delete("newKey", true) + }() + + newKey := "/newKey" + newValue := "/newValue" + + // This should succeed + resp, err := c.Create(newKey, newValue, 5) + if err != nil { + t.Fatal(err) + } + + if !(resp.Action == "create" && resp.Node.Key == newKey && + resp.Node.Value == newValue && resp.Node.TTL == 5) { + t.Fatalf("Create 1 failed: %#v", resp) + } + if resp.PrevNode != nil { + t.Fatalf("Create 1 PrevNode failed: %#v", resp) + } + + // This should fail, because the key is already there + resp, err = c.Create(newKey, newValue, 5) + if err == nil { + t.Fatalf("The key %v did exist, so the creation should have failed."+ + "The response was: %#v", resp.Node.Key, resp) + } +} + +func TestCreateInOrder(t *testing.T) { + c := NewClient(nil) + dir := "/queue" + defer func() { + c.DeleteDir(dir) + }() + + var firstKey, secondKey string + + resp, err := c.CreateInOrder(dir, "1", 5) + if err != nil { + t.Fatal(err) + } + + if !(resp.Action == "create" && resp.Node.Value == "1" && resp.Node.TTL == 5) { + t.Fatalf("Create 1 failed: %#v", resp) + } + + firstKey = resp.Node.Key + + resp, err = c.CreateInOrder(dir, "2", 5) + if err != nil { + t.Fatal(err) + } + + if !(resp.Action == "create" && resp.Node.Value == "2" && resp.Node.TTL == 5) { + t.Fatalf("Create 2 failed: %#v", resp) + } + + secondKey = resp.Node.Key + + if firstKey >= secondKey { + t.Fatalf("Expected first key to be greater than second key, but %s is not greater than %s", + firstKey, secondKey) + } +} + +func TestSetDir(t *testing.T) { + c := NewClient(nil) + defer func() { + c.Delete("foo", true) + c.Delete("fooDir", true) + }() + + resp, err := c.CreateDir("fooDir", 5) + if err != nil { + t.Fatal(err) + } + if !(resp.Node.Key == "/fooDir" && resp.Node.Value == "" && resp.Node.TTL == 5) { + t.Fatalf("SetDir 1 failed: %#v", resp) + } + if resp.PrevNode != nil { + t.Fatalf("SetDir 1 PrevNode failed: %#v", resp) + } + + // This should fail because /fooDir already points to a directory + resp, err = c.CreateDir("/fooDir", 5) + if err == nil { + t.Fatalf("fooDir already points to a directory, so SetDir should have failed."+ + "The response was: %#v", resp) + } + + _, err = c.Set("foo", "bar", 5) + if err != nil { + t.Fatal(err) + } + + // This should succeed + // It should replace the key + resp, err = c.SetDir("foo", 5) + if err != nil { + t.Fatal(err) + } + if !(resp.Node.Key == "/foo" && resp.Node.Value == "" && resp.Node.TTL == 5) { + t.Fatalf("SetDir 2 failed: %#v", resp) + } + if !(resp.PrevNode.Key == "/foo" && resp.PrevNode.Value == "bar" && resp.PrevNode.TTL == 5) { + t.Fatalf("SetDir 2 failed: %#v", resp) + } +} + +func TestUpdateDir(t *testing.T) { + c := NewClient(nil) + defer func() { + c.Delete("fooDir", true) + }() + + resp, err := c.CreateDir("fooDir", 5) + if err != nil { + t.Fatal(err) + } + + // This should succeed. + resp, err = c.UpdateDir("fooDir", 5) + if err != nil { + t.Fatal(err) + } + + if !(resp.Action == "update" && resp.Node.Key == "/fooDir" && + resp.Node.Value == "" && resp.Node.TTL == 5) { + t.Fatalf("UpdateDir 1 failed: %#v", resp) + } + if !(resp.PrevNode.Key == "/fooDir" && resp.PrevNode.Dir == true && resp.PrevNode.TTL == 5) { + t.Fatalf("UpdateDir 1 PrevNode failed: %#v", resp) + } + + // This should fail because the key does not exist. + resp, err = c.UpdateDir("nonexistentDir", 5) + if err == nil { + t.Fatalf("The key %v did not exist, so the update should have failed."+ + "The response was: %#v", resp.Node.Key, resp) + } +} + +func TestCreateDir(t *testing.T) { + c := NewClient(nil) + defer func() { + c.Delete("fooDir", true) + }() + + // This should succeed + resp, err := c.CreateDir("fooDir", 5) + if err != nil { + t.Fatal(err) + } + + if !(resp.Action == "create" && resp.Node.Key == "/fooDir" && + resp.Node.Value == "" && resp.Node.TTL == 5) { + t.Fatalf("CreateDir 1 failed: %#v", resp) + } + if resp.PrevNode != nil { + t.Fatalf("CreateDir 1 PrevNode failed: %#v", resp) + } + + // This should fail, because the key is already there + resp, err = c.CreateDir("fooDir", 5) + if err == nil { + t.Fatalf("The key %v did exist, so the creation should have failed."+ + "The response was: %#v", resp.Node.Key, resp) + } +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/version.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/version.go new file mode 100644 index 00000000..b1e9ed27 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/version.go @@ -0,0 +1,6 @@ +package etcd + +const ( + version = "v2" + packageVersion = "v2.0.0+git" +) diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/watch.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/watch.go new file mode 100644 index 00000000..aa8d3df3 --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/watch.go @@ -0,0 +1,103 @@ +package etcd + +import ( + "errors" +) + +// Errors introduced by the Watch command. +var ( + ErrWatchStoppedByUser = errors.New("Watch stopped by the user via stop channel") +) + +// If recursive is set to true the watch returns the first change under the given +// prefix since the given index. +// +// If recursive is set to false the watch returns the first change to the given key +// since the given index. +// +// To watch for the latest change, set waitIndex = 0. +// +// If a receiver channel is given, it will be a long-term watch. Watch will block at the +//channel. After someone receives the channel, it will go on to watch that +// prefix. If a stop channel is given, the client can close long-term watch using +// the stop channel. +func (c *Client) Watch(prefix string, waitIndex uint64, recursive bool, + receiver chan *Response, stop chan bool) (*Response, error) { + logger.Debugf("watch %s [%s]", prefix, c.cluster.Leader) + if receiver == nil { + raw, err := c.watchOnce(prefix, waitIndex, recursive, stop) + + if err != nil { + return nil, err + } + + return raw.Unmarshal() + } + defer close(receiver) + + for { + raw, err := c.watchOnce(prefix, waitIndex, recursive, stop) + + if err != nil { + return nil, err + } + + resp, err := raw.Unmarshal() + + if err != nil { + return nil, err + } + + waitIndex = resp.Node.ModifiedIndex + 1 + receiver <- resp + } +} + +func (c *Client) RawWatch(prefix string, waitIndex uint64, recursive bool, + receiver chan *RawResponse, stop chan bool) (*RawResponse, error) { + + logger.Debugf("rawWatch %s [%s]", prefix, c.cluster.Leader) + if receiver == nil { + return c.watchOnce(prefix, waitIndex, recursive, stop) + } + + for { + raw, err := c.watchOnce(prefix, waitIndex, recursive, stop) + + if err != nil { + return nil, err + } + + resp, err := raw.Unmarshal() + + if err != nil { + return nil, err + } + + waitIndex = resp.Node.ModifiedIndex + 1 + receiver <- raw + } +} + +// helper func +// return when there is change under the given prefix +func (c *Client) watchOnce(key string, waitIndex uint64, recursive bool, stop chan bool) (*RawResponse, error) { + + options := Options{ + "wait": true, + } + if waitIndex > 0 { + options["waitIndex"] = waitIndex + } + if recursive { + options["recursive"] = true + } + + resp, err := c.getCancelable(key, options, stop) + + if err == ErrRequestCancelled { + return nil, ErrWatchStoppedByUser + } + + return resp, err +} diff --git a/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/watch_test.go b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/watch_test.go new file mode 100644 index 00000000..43e1dfeb --- /dev/null +++ b/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/watch_test.go @@ -0,0 +1,119 @@ +package etcd + +import ( + "fmt" + "runtime" + "testing" + "time" +) + +func TestWatch(t *testing.T) { + c := NewClient(nil) + defer func() { + c.Delete("watch_foo", true) + }() + + go setHelper("watch_foo", "bar", c) + + resp, err := c.Watch("watch_foo", 0, false, nil, nil) + if err != nil { + t.Fatal(err) + } + if !(resp.Node.Key == "/watch_foo" && resp.Node.Value == "bar") { + t.Fatalf("Watch 1 failed: %#v", resp) + } + + go setHelper("watch_foo", "bar", c) + + resp, err = c.Watch("watch_foo", resp.Node.ModifiedIndex+1, false, nil, nil) + if err != nil { + t.Fatal(err) + } + if !(resp.Node.Key == "/watch_foo" && resp.Node.Value == "bar") { + t.Fatalf("Watch 2 failed: %#v", resp) + } + + routineNum := runtime.NumGoroutine() + + ch := make(chan *Response, 10) + stop := make(chan bool, 1) + + go setLoop("watch_foo", "bar", c) + + go receiver(ch, stop) + + _, err = c.Watch("watch_foo", 0, false, ch, stop) + if err != ErrWatchStoppedByUser { + t.Fatalf("Watch returned a non-user stop error") + } + + if newRoutineNum := runtime.NumGoroutine(); newRoutineNum != routineNum { + t.Fatalf("Routine numbers differ after watch stop: %v, %v", routineNum, newRoutineNum) + } +} + +func TestWatchAll(t *testing.T) { + c := NewClient(nil) + defer func() { + c.Delete("watch_foo", true) + }() + + go setHelper("watch_foo/foo", "bar", c) + + resp, err := c.Watch("watch_foo", 0, true, nil, nil) + if err != nil { + t.Fatal(err) + } + if !(resp.Node.Key == "/watch_foo/foo" && resp.Node.Value == "bar") { + t.Fatalf("WatchAll 1 failed: %#v", resp) + } + + go setHelper("watch_foo/foo", "bar", c) + + resp, err = c.Watch("watch_foo", resp.Node.ModifiedIndex+1, true, nil, nil) + if err != nil { + t.Fatal(err) + } + if !(resp.Node.Key == "/watch_foo/foo" && resp.Node.Value == "bar") { + t.Fatalf("WatchAll 2 failed: %#v", resp) + } + + ch := make(chan *Response, 10) + stop := make(chan bool, 1) + + routineNum := runtime.NumGoroutine() + + go setLoop("watch_foo/foo", "bar", c) + + go receiver(ch, stop) + + _, err = c.Watch("watch_foo", 0, true, ch, stop) + if err != ErrWatchStoppedByUser { + t.Fatalf("Watch returned a non-user stop error") + } + + if newRoutineNum := runtime.NumGoroutine(); newRoutineNum != routineNum { + t.Fatalf("Routine numbers differ after watch stop: %v, %v", routineNum, newRoutineNum) + } +} + +func setHelper(key, value string, c *Client) { + time.Sleep(time.Second) + c.Set(key, value, 100) +} + +func setLoop(key, value string, c *Client) { + time.Sleep(time.Second) + for i := 0; i < 10; i++ { + newValue := fmt.Sprintf("%s_%v", value, i) + c.Set(key, newValue, 100) + time.Sleep(time.Second / 10) + } +} + +func receiver(c chan *Response, stop chan bool) { + for i := 0; i < 10; i++ { + <-c + } + stop <- true +} diff --git a/Godeps/_workspace/src/github.com/kr/pretty/.gitignore b/Godeps/_workspace/src/github.com/kr/pretty/.gitignore new file mode 100644 index 00000000..1f0a99f2 --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/pretty/.gitignore @@ -0,0 +1,4 @@ +[568].out +_go* +_test* +_obj diff --git a/Godeps/_workspace/src/github.com/kr/pretty/License b/Godeps/_workspace/src/github.com/kr/pretty/License new file mode 100644 index 00000000..05c783cc --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/pretty/License @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright 2012 Keith Rarick + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Godeps/_workspace/src/github.com/kr/pretty/Readme b/Godeps/_workspace/src/github.com/kr/pretty/Readme new file mode 100644 index 00000000..c589fc62 --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/pretty/Readme @@ -0,0 +1,9 @@ +package pretty + + import "github.com/kr/pretty" + + Package pretty provides pretty-printing for Go values. + +Documentation + + http://godoc.org/github.com/kr/pretty diff --git a/Godeps/_workspace/src/github.com/kr/pretty/diff.go b/Godeps/_workspace/src/github.com/kr/pretty/diff.go new file mode 100644 index 00000000..8fe8e240 --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/pretty/diff.go @@ -0,0 +1,158 @@ +package pretty + +import ( + "fmt" + "io" + "reflect" +) + +type sbuf []string + +func (s *sbuf) Write(b []byte) (int, error) { + *s = append(*s, string(b)) + return len(b), nil +} + +// Diff returns a slice where each element describes +// a difference between a and b. +func Diff(a, b interface{}) (desc []string) { + Fdiff((*sbuf)(&desc), a, b) + return desc +} + +// Fdiff writes to w a description of the differences between a and b. +func Fdiff(w io.Writer, a, b interface{}) { + diffWriter{w: w}.diff(reflect.ValueOf(a), reflect.ValueOf(b)) +} + +type diffWriter struct { + w io.Writer + l string // label +} + +func (w diffWriter) printf(f string, a ...interface{}) { + var l string + if w.l != "" { + l = w.l + ": " + } + fmt.Fprintf(w.w, l+f, a...) +} + +func (w diffWriter) diff(av, bv reflect.Value) { + if !av.IsValid() && bv.IsValid() { + w.printf("nil != %#v", bv.Interface()) + return + } + if av.IsValid() && !bv.IsValid() { + w.printf("%#v != nil", av.Interface()) + return + } + if !av.IsValid() && !bv.IsValid() { + return + } + + at := av.Type() + bt := bv.Type() + if at != bt { + w.printf("%v != %v", at, bt) + return + } + + // numeric types, including bool + if at.Kind() < reflect.Array { + a, b := av.Interface(), bv.Interface() + if a != b { + w.printf("%#v != %#v", a, b) + } + return + } + + switch at.Kind() { + case reflect.String: + a, b := av.Interface(), bv.Interface() + if a != b { + w.printf("%q != %q", a, b) + } + case reflect.Ptr: + switch { + case av.IsNil() && !bv.IsNil(): + w.printf("nil != %v", bv.Interface()) + case !av.IsNil() && bv.IsNil(): + w.printf("%v != nil", av.Interface()) + case !av.IsNil() && !bv.IsNil(): + w.diff(av.Elem(), bv.Elem()) + } + case reflect.Struct: + for i := 0; i < av.NumField(); i++ { + w.relabel(at.Field(i).Name).diff(av.Field(i), bv.Field(i)) + } + case reflect.Slice: + lenA := av.Len() + lenB := bv.Len() + if lenA != lenB { + w.printf("%s[%d] != %s[%d]", av.Type(), lenA, bv.Type(), lenB) + break + } + for i := 0; i < lenA; i++ { + w.relabel(fmt.Sprintf("[%d]", i)).diff(av.Index(i), bv.Index(i)) + } + case reflect.Map: + ak, both, bk := keyDiff(av.MapKeys(), bv.MapKeys()) + for _, k := range ak { + w := w.relabel(fmt.Sprintf("[%#v]", k.Interface())) + w.printf("%q != (missing)", av.MapIndex(k)) + } + for _, k := range both { + w := w.relabel(fmt.Sprintf("[%#v]", k.Interface())) + w.diff(av.MapIndex(k), bv.MapIndex(k)) + } + for _, k := range bk { + w := w.relabel(fmt.Sprintf("[%#v]", k.Interface())) + w.printf("(missing) != %q", bv.MapIndex(k)) + } + case reflect.Interface: + w.diff(reflect.ValueOf(av.Interface()), reflect.ValueOf(bv.Interface())) + default: + if !reflect.DeepEqual(av.Interface(), bv.Interface()) { + w.printf("%# v != %# v", Formatter(av.Interface()), Formatter(bv.Interface())) + } + } +} + +func (d diffWriter) relabel(name string) (d1 diffWriter) { + d1 = d + if d.l != "" && name[0] != '[' { + d1.l += "." + } + d1.l += name + return d1 +} + +func keyDiff(a, b []reflect.Value) (ak, both, bk []reflect.Value) { + for _, av := range a { + inBoth := false + for _, bv := range b { + if reflect.DeepEqual(av.Interface(), bv.Interface()) { + inBoth = true + both = append(both, av) + break + } + } + if !inBoth { + ak = append(ak, av) + } + } + for _, bv := range b { + inBoth := false + for _, av := range a { + if reflect.DeepEqual(av.Interface(), bv.Interface()) { + inBoth = true + break + } + } + if !inBoth { + bk = append(bk, bv) + } + } + return +} diff --git a/Godeps/_workspace/src/github.com/kr/pretty/diff_test.go b/Godeps/_workspace/src/github.com/kr/pretty/diff_test.go new file mode 100644 index 00000000..3c388f13 --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/pretty/diff_test.go @@ -0,0 +1,74 @@ +package pretty + +import ( + "testing" +) + +type difftest struct { + a interface{} + b interface{} + exp []string +} + +type S struct { + A int + S *S + I interface{} + C []int +} + +var diffs = []difftest{ + {a: nil, b: nil}, + {a: S{A: 1}, b: S{A: 1}}, + + {0, "", []string{`int != string`}}, + {0, 1, []string{`0 != 1`}}, + {S{}, new(S), []string{`pretty.S != *pretty.S`}}, + {"a", "b", []string{`"a" != "b"`}}, + {S{}, S{A: 1}, []string{`A: 0 != 1`}}, + {new(S), &S{A: 1}, []string{`A: 0 != 1`}}, + {S{S: new(S)}, S{S: &S{A: 1}}, []string{`S.A: 0 != 1`}}, + {S{}, S{I: 0}, []string{`I: nil != 0`}}, + {S{I: 1}, S{I: "x"}, []string{`I: int != string`}}, + {S{}, S{C: []int{1}}, []string{`C: []int[0] != []int[1]`}}, + {S{C: []int{}}, S{C: []int{1}}, []string{`C: []int[0] != []int[1]`}}, + {S{C: []int{1, 2, 3}}, S{C: []int{1, 2, 4}}, []string{`C[2]: 3 != 4`}}, + {S{}, S{A: 1, S: new(S)}, []string{`A: 0 != 1`, `S: nil != &{0 []}`}}, +} + +func TestDiff(t *testing.T) { + for _, tt := range diffs { + got := Diff(tt.a, tt.b) + eq := len(got) == len(tt.exp) + if eq { + for i := range got { + eq = eq && got[i] == tt.exp[i] + } + } + if !eq { + t.Errorf("diffing % #v", tt.a) + t.Errorf("with % #v", tt.b) + diffdiff(t, got, tt.exp) + continue + } + } +} + +func diffdiff(t *testing.T, got, exp []string) { + minus(t, "unexpected:", got, exp) + minus(t, "missing:", exp, got) +} + +func minus(t *testing.T, s string, a, b []string) { + var i, j int + for i = 0; i < len(a); i++ { + for j = 0; j < len(b); j++ { + if a[i] == b[j] { + break + } + } + if j == len(b) { + t.Error(s, a[i]) + } + } +} diff --git a/Godeps/_workspace/src/github.com/kr/pretty/example_test.go b/Godeps/_workspace/src/github.com/kr/pretty/example_test.go new file mode 100644 index 00000000..b4386a48 --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/pretty/example_test.go @@ -0,0 +1,20 @@ +package pretty_test + +import ( + "fmt" + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/kr/pretty" +) + +func Example() { + type myType struct { + a, b int + } + var x = []myType{{1, 2}, {3, 4}, {5, 6}} + fmt.Printf("%# v", pretty.Formatter(x)) + // output: + // []pretty_test.myType{ + // {a:1, b:2}, + // {a:3, b:4}, + // {a:5, b:6}, + // } +} diff --git a/Godeps/_workspace/src/github.com/kr/pretty/formatter.go b/Godeps/_workspace/src/github.com/kr/pretty/formatter.go new file mode 100644 index 00000000..5cb52a3f --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/pretty/formatter.go @@ -0,0 +1,337 @@ +package pretty + +import ( + "fmt" + "io" + "reflect" + "strconv" + "text/tabwriter" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/kr/text" +) + +const ( + limit = 50 +) + +type formatter struct { + x interface{} + force bool + quote bool +} + +// Formatter makes a wrapper, f, that will format x as go source with line +// breaks and tabs. Object f responds to the "%v" formatting verb when both the +// "#" and " " (space) flags are set, for example: +// +// fmt.Sprintf("%# v", Formatter(x)) +// +// If one of these two flags is not set, or any other verb is used, f will +// format x according to the usual rules of package fmt. +// In particular, if x satisfies fmt.Formatter, then x.Format will be called. +func Formatter(x interface{}) (f fmt.Formatter) { + return formatter{x: x, quote: true} +} + +func (fo formatter) String() string { + return fmt.Sprint(fo.x) // unwrap it +} + +func (fo formatter) passThrough(f fmt.State, c rune) { + s := "%" + for i := 0; i < 128; i++ { + if f.Flag(i) { + s += string(i) + } + } + if w, ok := f.Width(); ok { + s += fmt.Sprintf("%d", w) + } + if p, ok := f.Precision(); ok { + s += fmt.Sprintf(".%d", p) + } + s += string(c) + fmt.Fprintf(f, s, fo.x) +} + +func (fo formatter) Format(f fmt.State, c rune) { + if fo.force || c == 'v' && f.Flag('#') && f.Flag(' ') { + w := tabwriter.NewWriter(f, 4, 4, 1, ' ', 0) + p := &printer{tw: w, Writer: w, visited: make(map[visit]int)} + p.printValue(reflect.ValueOf(fo.x), true, fo.quote) + w.Flush() + return + } + fo.passThrough(f, c) +} + +type printer struct { + io.Writer + tw *tabwriter.Writer + visited map[visit]int + depth int +} + +func (p *printer) indent() *printer { + q := *p + q.tw = tabwriter.NewWriter(p.Writer, 4, 4, 1, ' ', 0) + q.Writer = text.NewIndentWriter(q.tw, []byte{'\t'}) + return &q +} + +func (p *printer) printInline(v reflect.Value, x interface{}, showType bool) { + if showType { + io.WriteString(p, v.Type().String()) + fmt.Fprintf(p, "(%#v)", x) + } else { + fmt.Fprintf(p, "%#v", x) + } +} + +// printValue must keep track of already-printed pointer values to avoid +// infinite recursion. +type visit struct { + v uintptr + typ reflect.Type +} + +func (p *printer) printValue(v reflect.Value, showType, quote bool) { + if p.depth > 10 { + io.WriteString(p, "!%v(DEPTH EXCEEDED)") + return + } + + switch v.Kind() { + case reflect.Bool: + p.printInline(v, v.Bool(), showType) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + p.printInline(v, v.Int(), showType) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + p.printInline(v, v.Uint(), showType) + case reflect.Float32, reflect.Float64: + p.printInline(v, v.Float(), showType) + case reflect.Complex64, reflect.Complex128: + fmt.Fprintf(p, "%#v", v.Complex()) + case reflect.String: + p.fmtString(v.String(), quote) + case reflect.Map: + t := v.Type() + if showType { + io.WriteString(p, t.String()) + } + writeByte(p, '{') + if nonzero(v) { + expand := !canInline(v.Type()) + pp := p + if expand { + writeByte(p, '\n') + pp = p.indent() + } + keys := v.MapKeys() + for i := 0; i < v.Len(); i++ { + showTypeInStruct := true + k := keys[i] + mv := v.MapIndex(k) + pp.printValue(k, false, true) + writeByte(pp, ':') + if expand { + writeByte(pp, '\t') + } + showTypeInStruct = t.Elem().Kind() == reflect.Interface + pp.printValue(mv, showTypeInStruct, true) + if expand { + io.WriteString(pp, ",\n") + } else if i < v.Len()-1 { + io.WriteString(pp, ", ") + } + } + if expand { + pp.tw.Flush() + } + } + writeByte(p, '}') + case reflect.Struct: + t := v.Type() + if v.CanAddr() { + addr := v.UnsafeAddr() + vis := visit{addr, t} + if vd, ok := p.visited[vis]; ok && vd < p.depth { + p.fmtString(t.String()+"{(CYCLIC REFERENCE)}", false) + break // don't print v again + } + p.visited[vis] = p.depth + } + + if showType { + io.WriteString(p, t.String()) + } + writeByte(p, '{') + if nonzero(v) { + expand := !canInline(v.Type()) + pp := p + if expand { + writeByte(p, '\n') + pp = p.indent() + } + for i := 0; i < v.NumField(); i++ { + showTypeInStruct := true + if f := t.Field(i); f.Name != "" { + io.WriteString(pp, f.Name) + writeByte(pp, ':') + if expand { + writeByte(pp, '\t') + } + showTypeInStruct = labelType(f.Type) + } + pp.printValue(getField(v, i), showTypeInStruct, true) + if expand { + io.WriteString(pp, ",\n") + } else if i < v.NumField()-1 { + io.WriteString(pp, ", ") + } + } + if expand { + pp.tw.Flush() + } + } + writeByte(p, '}') + case reflect.Interface: + switch e := v.Elem(); { + case e.Kind() == reflect.Invalid: + io.WriteString(p, "nil") + case e.IsValid(): + pp := *p + pp.depth++ + pp.printValue(e, showType, true) + default: + io.WriteString(p, v.Type().String()) + io.WriteString(p, "(nil)") + } + case reflect.Array, reflect.Slice: + t := v.Type() + if showType { + io.WriteString(p, t.String()) + } + if v.Kind() == reflect.Slice && v.IsNil() && showType { + io.WriteString(p, "(nil)") + break + } + if v.Kind() == reflect.Slice && v.IsNil() { + io.WriteString(p, "nil") + break + } + writeByte(p, '{') + expand := !canInline(v.Type()) + pp := p + if expand { + writeByte(p, '\n') + pp = p.indent() + } + for i := 0; i < v.Len(); i++ { + showTypeInSlice := t.Elem().Kind() == reflect.Interface + pp.printValue(v.Index(i), showTypeInSlice, true) + if expand { + io.WriteString(pp, ",\n") + } else if i < v.Len()-1 { + io.WriteString(pp, ", ") + } + } + if expand { + pp.tw.Flush() + } + writeByte(p, '}') + case reflect.Ptr: + e := v.Elem() + if !e.IsValid() { + writeByte(p, '(') + io.WriteString(p, v.Type().String()) + io.WriteString(p, ")(nil)") + } else { + pp := *p + pp.depth++ + writeByte(pp, '&') + pp.printValue(e, true, true) + } + case reflect.Chan: + x := v.Pointer() + if showType { + writeByte(p, '(') + io.WriteString(p, v.Type().String()) + fmt.Fprintf(p, ")(%#v)", x) + } else { + fmt.Fprintf(p, "%#v", x) + } + case reflect.Func: + io.WriteString(p, v.Type().String()) + io.WriteString(p, " {...}") + case reflect.UnsafePointer: + p.printInline(v, v.Pointer(), showType) + case reflect.Invalid: + io.WriteString(p, "nil") + } +} + +func canInline(t reflect.Type) bool { + switch t.Kind() { + case reflect.Map: + return !canExpand(t.Elem()) + case reflect.Struct: + for i := 0; i < t.NumField(); i++ { + if canExpand(t.Field(i).Type) { + return false + } + } + return true + case reflect.Interface: + return false + case reflect.Array, reflect.Slice: + return !canExpand(t.Elem()) + case reflect.Ptr: + return false + case reflect.Chan, reflect.Func, reflect.UnsafePointer: + return false + } + return true +} + +func canExpand(t reflect.Type) bool { + switch t.Kind() { + case reflect.Map, reflect.Struct, + reflect.Interface, reflect.Array, reflect.Slice, + reflect.Ptr: + return true + } + return false +} + +func labelType(t reflect.Type) bool { + switch t.Kind() { + case reflect.Interface, reflect.Struct: + return true + } + return false +} + +func (p *printer) fmtString(s string, quote bool) { + if quote { + s = strconv.Quote(s) + } + io.WriteString(p, s) +} + +func tryDeepEqual(a, b interface{}) bool { + defer func() { recover() }() + return reflect.DeepEqual(a, b) +} + +func writeByte(w io.Writer, b byte) { + w.Write([]byte{b}) +} + +func getField(v reflect.Value, i int) reflect.Value { + val := v.Field(i) + if val.Kind() == reflect.Interface && !val.IsNil() { + val = val.Elem() + } + return val +} diff --git a/Godeps/_workspace/src/github.com/kr/pretty/formatter_test.go b/Godeps/_workspace/src/github.com/kr/pretty/formatter_test.go new file mode 100644 index 00000000..5f3204e8 --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/pretty/formatter_test.go @@ -0,0 +1,261 @@ +package pretty + +import ( + "fmt" + "io" + "strings" + "testing" + "unsafe" +) + +type test struct { + v interface{} + s string +} + +type LongStructTypeName struct { + longFieldName interface{} + otherLongFieldName interface{} +} + +type SA struct { + t *T + v T +} + +type T struct { + x, y int +} + +type F int + +func (f F) Format(s fmt.State, c rune) { + fmt.Fprintf(s, "F(%d)", int(f)) +} + +var long = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + +var gosyntax = []test{ + {nil, `nil`}, + {"", `""`}, + {"a", `"a"`}, + {1, "int(1)"}, + {1.0, "float64(1)"}, + {[]int(nil), "[]int(nil)"}, + {[0]int{}, "[0]int{}"}, + {complex(1, 0), "(1+0i)"}, + //{make(chan int), "(chan int)(0x1234)"}, + {unsafe.Pointer(uintptr(unsafe.Pointer(&long))), fmt.Sprintf("unsafe.Pointer(0x%02x)", uintptr(unsafe.Pointer(&long)))}, + {func(int) {}, "func(int) {...}"}, + {map[int]int{1: 1}, "map[int]int{1:1}"}, + {int32(1), "int32(1)"}, + {io.EOF, `&errors.errorString{s:"EOF"}`}, + {[]string{"a"}, `[]string{"a"}`}, + { + []string{long}, + `[]string{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"}`, + }, + {F(5), "pretty.F(5)"}, + { + SA{&T{1, 2}, T{3, 4}}, + `pretty.SA{ + t: &pretty.T{x:1, y:2}, + v: pretty.T{x:3, y:4}, +}`, + }, + { + map[int][]byte{1: {}}, + `map[int][]uint8{ + 1: {}, +}`, + }, + { + map[int]T{1: {}}, + `map[int]pretty.T{ + 1: {}, +}`, + }, + { + long, + `"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"`, + }, + { + LongStructTypeName{ + longFieldName: LongStructTypeName{}, + otherLongFieldName: long, + }, + `pretty.LongStructTypeName{ + longFieldName: pretty.LongStructTypeName{}, + otherLongFieldName: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", +}`, + }, + { + &LongStructTypeName{ + longFieldName: &LongStructTypeName{}, + otherLongFieldName: (*LongStructTypeName)(nil), + }, + `&pretty.LongStructTypeName{ + longFieldName: &pretty.LongStructTypeName{}, + otherLongFieldName: (*pretty.LongStructTypeName)(nil), +}`, + }, + { + []LongStructTypeName{ + {nil, nil}, + {3, 3}, + {long, nil}, + }, + `[]pretty.LongStructTypeName{ + {}, + { + longFieldName: int(3), + otherLongFieldName: int(3), + }, + { + longFieldName: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", + otherLongFieldName: nil, + }, +}`, + }, + { + []interface{}{ + LongStructTypeName{nil, nil}, + []byte{1, 2, 3}, + T{3, 4}, + LongStructTypeName{long, nil}, + }, + `[]interface {}{ + pretty.LongStructTypeName{}, + []uint8{0x1, 0x2, 0x3}, + pretty.T{x:3, y:4}, + pretty.LongStructTypeName{ + longFieldName: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", + otherLongFieldName: nil, + }, +}`, + }, +} + +func TestGoSyntax(t *testing.T) { + for _, tt := range gosyntax { + s := fmt.Sprintf("%# v", Formatter(tt.v)) + if tt.s != s { + t.Errorf("expected %q", tt.s) + t.Errorf("got %q", s) + t.Errorf("expraw\n%s", tt.s) + t.Errorf("gotraw\n%s", s) + } + } +} + +type I struct { + i int + R interface{} +} + +func (i *I) I() *I { return i.R.(*I) } + +func TestCycle(t *testing.T) { + type A struct{ *A } + v := &A{} + v.A = v + + // panics from stack overflow without cycle detection + t.Logf("Example cycle:\n%# v", Formatter(v)) + + p := &A{} + s := fmt.Sprintf("%# v", Formatter([]*A{p, p})) + if strings.Contains(s, "CYCLIC") { + t.Errorf("Repeated address detected as cyclic reference:\n%s", s) + } + + type R struct { + i int + *R + } + r := &R{ + i: 1, + R: &R{ + i: 2, + R: &R{ + i: 3, + }, + }, + } + r.R.R.R = r + t.Logf("Example longer cycle:\n%# v", Formatter(r)) + + r = &R{ + i: 1, + R: &R{ + i: 2, + R: &R{ + i: 3, + R: &R{ + i: 4, + R: &R{ + i: 5, + R: &R{ + i: 6, + R: &R{ + i: 7, + R: &R{ + i: 8, + R: &R{ + i: 9, + R: &R{ + i: 10, + R: &R{ + i: 11, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + // here be pirates + r.R.R.R.R.R.R.R.R.R.R.R = r + t.Logf("Example very long cycle:\n%# v", Formatter(r)) + + i := &I{ + i: 1, + R: &I{ + i: 2, + R: &I{ + i: 3, + R: &I{ + i: 4, + R: &I{ + i: 5, + R: &I{ + i: 6, + R: &I{ + i: 7, + R: &I{ + i: 8, + R: &I{ + i: 9, + R: &I{ + i: 10, + R: &I{ + i: 11, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + iv := i.I().I().I().I().I().I().I().I().I().I() + *iv = *i + t.Logf("Example long interface cycle:\n%# v", Formatter(i)) +} diff --git a/Godeps/_workspace/src/github.com/kr/pretty/pretty.go b/Godeps/_workspace/src/github.com/kr/pretty/pretty.go new file mode 100644 index 00000000..d3df8686 --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/pretty/pretty.go @@ -0,0 +1,98 @@ +// Package pretty provides pretty-printing for Go values. This is +// useful during debugging, to avoid wrapping long output lines in +// the terminal. +// +// It provides a function, Formatter, that can be used with any +// function that accepts a format string. It also provides +// convenience wrappers for functions in packages fmt and log. +package pretty + +import ( + "fmt" + "io" + "log" +) + +// Errorf is a convenience wrapper for fmt.Errorf. +// +// Calling Errorf(f, x, y) is equivalent to +// fmt.Errorf(f, Formatter(x), Formatter(y)). +func Errorf(format string, a ...interface{}) error { + return fmt.Errorf(format, wrap(a, false)...) +} + +// Fprintf is a convenience wrapper for fmt.Fprintf. +// +// Calling Fprintf(w, f, x, y) is equivalent to +// fmt.Fprintf(w, f, Formatter(x), Formatter(y)). +func Fprintf(w io.Writer, format string, a ...interface{}) (n int, error error) { + return fmt.Fprintf(w, format, wrap(a, false)...) +} + +// Log is a convenience wrapper for log.Printf. +// +// Calling Log(x, y) is equivalent to +// log.Print(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Log(a ...interface{}) { + log.Print(wrap(a, true)...) +} + +// Logf is a convenience wrapper for log.Printf. +// +// Calling Logf(f, x, y) is equivalent to +// log.Printf(f, Formatter(x), Formatter(y)). +func Logf(format string, a ...interface{}) { + log.Printf(format, wrap(a, false)...) +} + +// Logln is a convenience wrapper for log.Printf. +// +// Calling Logln(x, y) is equivalent to +// log.Println(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Logln(a ...interface{}) { + log.Println(wrap(a, true)...) +} + +// Print pretty-prints its operands and writes to standard output. +// +// Calling Print(x, y) is equivalent to +// fmt.Print(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Print(a ...interface{}) (n int, errno error) { + return fmt.Print(wrap(a, true)...) +} + +// Printf is a convenience wrapper for fmt.Printf. +// +// Calling Printf(f, x, y) is equivalent to +// fmt.Printf(f, Formatter(x), Formatter(y)). +func Printf(format string, a ...interface{}) (n int, errno error) { + return fmt.Printf(format, wrap(a, false)...) +} + +// Println pretty-prints its operands and writes to standard output. +// +// Calling Print(x, y) is equivalent to +// fmt.Println(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Println(a ...interface{}) (n int, errno error) { + return fmt.Println(wrap(a, true)...) +} + +// Sprintf is a convenience wrapper for fmt.Sprintf. +// +// Calling Sprintf(f, x, y) is equivalent to +// fmt.Sprintf(f, Formatter(x), Formatter(y)). +func Sprintf(format string, a ...interface{}) string { + return fmt.Sprintf(format, wrap(a, false)...) +} + +func wrap(a []interface{}, force bool) []interface{} { + w := make([]interface{}, len(a)) + for i, x := range a { + w[i] = formatter{x: x, force: force} + } + return w +} diff --git a/Godeps/_workspace/src/github.com/kr/pretty/zero.go b/Godeps/_workspace/src/github.com/kr/pretty/zero.go new file mode 100644 index 00000000..abb5b6fc --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/pretty/zero.go @@ -0,0 +1,41 @@ +package pretty + +import ( + "reflect" +) + +func nonzero(v reflect.Value) bool { + switch v.Kind() { + case reflect.Bool: + return v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() != 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() != 0 + case reflect.Float32, reflect.Float64: + return v.Float() != 0 + case reflect.Complex64, reflect.Complex128: + return v.Complex() != complex(0, 0) + case reflect.String: + return v.String() != "" + case reflect.Struct: + for i := 0; i < v.NumField(); i++ { + if nonzero(getField(v, i)) { + return true + } + } + return false + case reflect.Array: + for i := 0; i < v.Len(); i++ { + if nonzero(v.Index(i)) { + return true + } + } + return false + case reflect.Map, reflect.Interface, reflect.Slice, reflect.Ptr, reflect.Chan, reflect.Func: + return !v.IsNil() + case reflect.UnsafePointer: + return v.Pointer() != 0 + } + return true +} diff --git a/Godeps/_workspace/src/github.com/kr/text/License b/Godeps/_workspace/src/github.com/kr/text/License new file mode 100644 index 00000000..480a3280 --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/text/License @@ -0,0 +1,19 @@ +Copyright 2012 Keith Rarick + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Godeps/_workspace/src/github.com/kr/text/Readme b/Godeps/_workspace/src/github.com/kr/text/Readme new file mode 100644 index 00000000..7e6e7c06 --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/text/Readme @@ -0,0 +1,3 @@ +This is a Go package for manipulating paragraphs of text. + +See http://go.pkgdoc.org/github.com/kr/text for full documentation. diff --git a/Godeps/_workspace/src/github.com/kr/text/colwriter/Readme b/Godeps/_workspace/src/github.com/kr/text/colwriter/Readme new file mode 100644 index 00000000..1c1f4e68 --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/text/colwriter/Readme @@ -0,0 +1,5 @@ +Package colwriter provides a write filter that formats +input lines in multiple columns. + +The package is a straightforward translation from +/src/cmd/draw/mc.c in Plan 9 from User Space. diff --git a/Godeps/_workspace/src/github.com/kr/text/colwriter/column.go b/Godeps/_workspace/src/github.com/kr/text/colwriter/column.go new file mode 100644 index 00000000..7302ce9f --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/text/colwriter/column.go @@ -0,0 +1,147 @@ +// Package colwriter provides a write filter that formats +// input lines in multiple columns. +// +// The package is a straightforward translation from +// /src/cmd/draw/mc.c in Plan 9 from User Space. +package colwriter + +import ( + "bytes" + "io" + "unicode/utf8" +) + +const ( + tab = 4 +) + +const ( + // Print each input line ending in a colon ':' separately. + BreakOnColon uint = 1 << iota +) + +// A Writer is a filter that arranges input lines in as many columns as will +// fit in its width. Tab '\t' chars in the input are translated to sequences +// of spaces ending at multiples of 4 positions. +// +// If BreakOnColon is set, each input line ending in a colon ':' is written +// separately. +// +// The Writer assumes that all Unicode code points have the same width; this +// may not be true in some fonts. +type Writer struct { + w io.Writer + buf []byte + width int + flag uint +} + +// NewWriter allocates and initializes a new Writer writing to w. +// Parameter width controls the total number of characters on each line +// across all columns. +func NewWriter(w io.Writer, width int, flag uint) *Writer { + return &Writer{ + w: w, + width: width, + flag: flag, + } +} + +// Write writes p to the writer w. The only errors returned are ones +// encountered while writing to the underlying output stream. +func (w *Writer) Write(p []byte) (n int, err error) { + var linelen int + var lastWasColon bool + for i, c := range p { + w.buf = append(w.buf, c) + linelen++ + if c == '\t' { + w.buf[len(w.buf)-1] = ' ' + for linelen%tab != 0 { + w.buf = append(w.buf, ' ') + linelen++ + } + } + if w.flag&BreakOnColon != 0 && c == ':' { + lastWasColon = true + } else if lastWasColon { + if c == '\n' { + pos := bytes.LastIndex(w.buf[:len(w.buf)-1], []byte{'\n'}) + if pos < 0 { + pos = 0 + } + line := w.buf[pos:] + w.buf = w.buf[:pos] + if err = w.columnate(); err != nil { + if len(line) < i { + return i - len(line), err + } + return 0, err + } + if n, err := w.w.Write(line); err != nil { + if r := len(line) - n; r < i { + return i - r, err + } + return 0, err + } + } + lastWasColon = false + } + if c == '\n' { + linelen = 0 + } + } + return len(p), nil +} + +// Flush should be called after the last call to Write to ensure that any data +// buffered in the Writer is written to output. +func (w *Writer) Flush() error { + return w.columnate() +} + +func (w *Writer) columnate() error { + words := bytes.Split(w.buf, []byte{'\n'}) + w.buf = nil + if len(words[len(words)-1]) == 0 { + words = words[:len(words)-1] + } + maxwidth := 0 + for _, wd := range words { + if n := utf8.RuneCount(wd); n > maxwidth { + maxwidth = n + } + } + maxwidth++ // space char + wordsPerLine := w.width / maxwidth + if wordsPerLine <= 0 { + wordsPerLine = 1 + } + nlines := (len(words) + wordsPerLine - 1) / wordsPerLine + for i := 0; i < nlines; i++ { + col := 0 + endcol := 0 + for j := i; j < len(words); j += nlines { + endcol += maxwidth + _, err := w.w.Write(words[j]) + if err != nil { + return err + } + col += utf8.RuneCount(words[j]) + if j+nlines < len(words) { + for col < endcol { + _, err := w.w.Write([]byte{' '}) + if err != nil { + return err + } + col++ + } + } + } + _, err := w.w.Write([]byte{'\n'}) + if err != nil { + return err + } + } + return nil +} diff --git a/Godeps/_workspace/src/github.com/kr/text/colwriter/column_test.go b/Godeps/_workspace/src/github.com/kr/text/colwriter/column_test.go new file mode 100644 index 00000000..ce388f5a --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/text/colwriter/column_test.go @@ -0,0 +1,90 @@ +package colwriter + +import ( + "bytes" + "testing" +) + +var src = ` +.git +.gitignore +.godir +Procfile: +README.md +api.go +apps.go +auth.go +darwin.go +data.go +dyno.go: +env.go +git.go +help.go +hkdist +linux.go +ls.go +main.go +plugin.go +run.go +scale.go +ssh.go +tail.go +term +unix.go +update.go +version.go +windows.go +`[1:] + +var tests = []struct { + wid int + flag uint + src string + want string +}{ + {80, 0, "", ""}, + {80, 0, src, ` +.git README.md darwin.go git.go ls.go scale.go unix.go +.gitignore api.go data.go help.go main.go ssh.go update.go +.godir apps.go dyno.go: hkdist plugin.go tail.go version.go +Procfile: auth.go env.go linux.go run.go term windows.go +`[1:]}, + {80, BreakOnColon, src, ` +.git .gitignore .godir + +Procfile: +README.md api.go apps.go auth.go darwin.go data.go + +dyno.go: +env.go hkdist main.go scale.go term version.go +git.go linux.go plugin.go ssh.go unix.go windows.go +help.go ls.go run.go tail.go update.go +`[1:]}, + {20, 0, ` +Hello +Γειά σου +안녕 +今日は +`[1:], ` +Hello 안녕 +Γειά σου 今日は +`[1:]}, +} + +func TestWriter(t *testing.T) { + for _, test := range tests { + b := new(bytes.Buffer) + w := NewWriter(b, test.wid, test.flag) + if _, err := w.Write([]byte(test.src)); err != nil { + t.Error(err) + } + if err := w.Flush(); err != nil { + t.Error(err) + } + if g := b.String(); test.want != g { + t.Log("\n" + test.want) + t.Log("\n" + g) + t.Errorf("%q != %q", test.want, g) + } + } +} diff --git a/Godeps/_workspace/src/github.com/kr/text/doc.go b/Godeps/_workspace/src/github.com/kr/text/doc.go new file mode 100644 index 00000000..cf4c198f --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/text/doc.go @@ -0,0 +1,3 @@ +// Package text provides rudimentary functions for manipulating text in +// paragraphs. +package text diff --git a/Godeps/_workspace/src/github.com/kr/text/indent.go b/Godeps/_workspace/src/github.com/kr/text/indent.go new file mode 100644 index 00000000..4ebac45c --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/text/indent.go @@ -0,0 +1,74 @@ +package text + +import ( + "io" +) + +// Indent inserts prefix at the beginning of each non-empty line of s. The +// end-of-line marker is NL. +func Indent(s, prefix string) string { + return string(IndentBytes([]byte(s), []byte(prefix))) +} + +// IndentBytes inserts prefix at the beginning of each non-empty line of b. +// The end-of-line marker is NL. +func IndentBytes(b, prefix []byte) []byte { + var res []byte + bol := true + for _, c := range b { + if bol && c != '\n' { + res = append(res, prefix...) + } + res = append(res, c) + bol = c == '\n' + } + return res +} + +// Writer indents each line of its input. +type indentWriter struct { + w io.Writer + bol bool + pre [][]byte + sel int + off int +} + +// NewIndentWriter makes a new write filter that indents the input +// lines. Each line is prefixed in order with the corresponding +// element of pre. If there are more lines than elements, the last +// element of pre is repeated for each subsequent line. +func NewIndentWriter(w io.Writer, pre ...[]byte) io.Writer { + return &indentWriter{ + w: w, + pre: pre, + bol: true, + } +} + +// The only errors returned are from the underlying indentWriter. +func (w *indentWriter) Write(p []byte) (n int, err error) { + for _, c := range p { + if w.bol { + var i int + i, err = w.w.Write(w.pre[w.sel][w.off:]) + w.off += i + if err != nil { + return n, err + } + } + _, err = w.w.Write([]byte{c}) + if err != nil { + return n, err + } + n++ + w.bol = c == '\n' + if w.bol { + w.off = 0 + if w.sel < len(w.pre)-1 { + w.sel++ + } + } + } + return n, nil +} diff --git a/Godeps/_workspace/src/github.com/kr/text/indent_test.go b/Godeps/_workspace/src/github.com/kr/text/indent_test.go new file mode 100644 index 00000000..5c723eee --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/text/indent_test.go @@ -0,0 +1,119 @@ +package text + +import ( + "bytes" + "testing" +) + +type T struct { + inp, exp, pre string +} + +var tests = []T{ + { + "The quick brown fox\njumps over the lazy\ndog.\nBut not quickly.\n", + "xxxThe quick brown fox\nxxxjumps over the lazy\nxxxdog.\nxxxBut not quickly.\n", + "xxx", + }, + { + "The quick brown fox\njumps over the lazy\ndog.\n\nBut not quickly.", + "xxxThe quick brown fox\nxxxjumps over the lazy\nxxxdog.\n\nxxxBut not quickly.", + "xxx", + }, +} + +func TestIndent(t *testing.T) { + for _, test := range tests { + got := Indent(test.inp, test.pre) + if got != test.exp { + t.Errorf("mismatch %q != %q", got, test.exp) + } + } +} + +type IndentWriterTest struct { + inp, exp string + pre []string +} + +var ts = []IndentWriterTest{ + { + ` +The quick brown fox +jumps over the lazy +dog. +But not quickly. +`[1:], + ` +xxxThe quick brown fox +xxxjumps over the lazy +xxxdog. +xxxBut not quickly. +`[1:], + []string{"xxx"}, + }, + { + ` +The quick brown fox +jumps over the lazy +dog. +But not quickly. +`[1:], + ` +xxaThe quick brown fox +xxxjumps over the lazy +xxxdog. +xxxBut not quickly. +`[1:], + []string{"xxa", "xxx"}, + }, + { + ` +The quick brown fox +jumps over the lazy +dog. +But not quickly. +`[1:], + ` +xxaThe quick brown fox +xxbjumps over the lazy +xxcdog. +xxxBut not quickly. +`[1:], + []string{"xxa", "xxb", "xxc", "xxx"}, + }, + { + ` +The quick brown fox +jumps over the lazy +dog. + +But not quickly.`[1:], + ` +xxaThe quick brown fox +xxxjumps over the lazy +xxxdog. +xxx +xxxBut not quickly.`[1:], + []string{"xxa", "xxx"}, + }, +} + +func TestIndentWriter(t *testing.T) { + for _, test := range ts { + b := new(bytes.Buffer) + pre := make([][]byte, len(test.pre)) + for i := range test.pre { + pre[i] = []byte(test.pre[i]) + } + w := NewIndentWriter(b, pre...) + if _, err := w.Write([]byte(test.inp)); err != nil { + t.Error(err) + } + if got := b.String(); got != test.exp { + t.Errorf("mismatch %q != %q", got, test.exp) + t.Log(got) + t.Log(test.exp) + } + } +} diff --git a/Godeps/_workspace/src/github.com/kr/text/mc/Readme b/Godeps/_workspace/src/github.com/kr/text/mc/Readme new file mode 100644 index 00000000..519ddc00 --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/text/mc/Readme @@ -0,0 +1,9 @@ +Command mc prints in multiple columns. + + Usage: mc [-] [-N] [file...] + +Mc splits the input into as many columns as will fit in N +print positions. If the output is a tty, the default N is +the number of characters in a terminal line; otherwise the +default N is 80. Under option - each input line ending in +a colon ':' is printed separately. diff --git a/Godeps/_workspace/src/github.com/kr/text/mc/mc.go b/Godeps/_workspace/src/github.com/kr/text/mc/mc.go new file mode 100644 index 00000000..7b29c790 --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/text/mc/mc.go @@ -0,0 +1,62 @@ +// Command mc prints in multiple columns. +// +// Usage: mc [-] [-N] [file...] +// +// Mc splits the input into as many columns as will fit in N +// print positions. If the output is a tty, the default N is +// the number of characters in a terminal line; otherwise the +// default N is 80. Under option - each input line ending in +// a colon ':' is printed separately. +package main + +import ( + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/kr/text/colwriter" + "github.com/kr/pty" + "io" + "log" + "os" + "strconv" +) + +func main() { + var width int + var flag uint + args := os.Args[1:] + for len(args) > 0 && len(args[0]) > 0 && args[0][0] == '-' { + if len(args[0]) > 1 { + width, _ = strconv.Atoi(args[0][1:]) + } else { + flag |= colwriter.BreakOnColon + } + args = args[1:] + } + if width < 1 { + _, width, _ = pty.Getsize(os.Stdout) + } + if width < 1 { + width = 80 + } + + w := colwriter.NewWriter(os.Stdout, width, flag) + if len(args) > 0 { + for _, s := range args { + if f, err := os.Open(s); err == nil { + copyin(w, f) + f.Close() + } else { + log.Println(err) + } + } + } else { + copyin(w, os.Stdin) + } +} + +func copyin(w *colwriter.Writer, r io.Reader) { + if _, err := io.Copy(w, r); err != nil { + log.Println(err) + } + if err := w.Flush(); err != nil { + log.Println(err) + } +} diff --git a/Godeps/_workspace/src/github.com/kr/text/wrap.go b/Godeps/_workspace/src/github.com/kr/text/wrap.go new file mode 100644 index 00000000..1c85cd2c --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/text/wrap.go @@ -0,0 +1,86 @@ +package text + +import ( + "bytes" + "math" +) + +var ( + nl = []byte{'\n'} + sp = []byte{' '} +) + +const defaultPenalty = 1e5 + +// Wrap wraps s into a paragraph of lines of length lim, with minimal +// raggedness. +func Wrap(s string, lim int) string { + return string(WrapBytes([]byte(s), lim)) +} + +// WrapBytes wraps b into a paragraph of lines of length lim, with minimal +// raggedness. +func WrapBytes(b []byte, lim int) []byte { + words := bytes.Split(bytes.Replace(bytes.TrimSpace(b), nl, sp, -1), sp) + var lines [][]byte + for _, line := range WrapWords(words, 1, lim, defaultPenalty) { + lines = append(lines, bytes.Join(line, sp)) + } + return bytes.Join(lines, nl) +} + +// WrapWords is the low-level line-breaking algorithm, useful if you need more +// control over the details of the text wrapping process. For most uses, either +// Wrap or WrapBytes will be sufficient and more convenient. +// +// WrapWords splits a list of words into lines with minimal "raggedness", +// treating each byte as one unit, accounting for spc units between adjacent +// words on each line, and attempting to limit lines to lim units. Raggedness +// is the total error over all lines, where error is the square of the +// difference of the length of the line and lim. Too-long lines (which only +// happen when a single word is longer than lim units) have pen penalty units +// added to the error. +func WrapWords(words [][]byte, spc, lim, pen int) [][][]byte { + n := len(words) + + length := make([][]int, n) + for i := 0; i < n; i++ { + length[i] = make([]int, n) + length[i][i] = len(words[i]) + for j := i + 1; j < n; j++ { + length[i][j] = length[i][j-1] + spc + len(words[j]) + } + } + + nbrk := make([]int, n) + cost := make([]int, n) + for i := range cost { + cost[i] = math.MaxInt32 + } + for i := n - 1; i >= 0; i-- { + if length[i][n-1] <= lim { + cost[i] = 0 + nbrk[i] = n + } else { + for j := i + 1; j < n; j++ { + d := lim - length[i][j-1] + c := d*d + cost[j] + if length[i][j-1] > lim { + c += pen // too-long lines get a worse penalty + } + if c < cost[i] { + cost[i] = c + nbrk[i] = j + } + } + } + } + + var lines [][][]byte + i := 0 + for i < n { + lines = append(lines, words[i:nbrk[i]]) + i = nbrk[i] + } + return lines +} diff --git a/Godeps/_workspace/src/github.com/kr/text/wrap_test.go b/Godeps/_workspace/src/github.com/kr/text/wrap_test.go new file mode 100644 index 00000000..90f065cd --- /dev/null +++ b/Godeps/_workspace/src/github.com/kr/text/wrap_test.go @@ -0,0 +1,44 @@ +package text + +import ( + "bytes" + "testing" +) + +var text = "The quick brown fox jumps over the lazy dog." + +func TestWrap(t *testing.T) { + exp := [][]string{ + {"The", "quick", "brown", "fox"}, + {"jumps", "over", "the", "lazy", "dog."}, + } + words := bytes.Split([]byte(text), sp) + got := WrapWords(words, 1, 24, defaultPenalty) + if len(exp) != len(got) { + t.Fail() + } + for i := range exp { + if len(exp[i]) != len(got[i]) { + t.Fail() + } + for j := range exp[i] { + if exp[i][j] != string(got[i][j]) { + t.Fatal(i, exp[i][j], got[i][j]) + } + } + } +} + +func TestWrapNarrow(t *testing.T) { + exp := "The\nquick\nbrown\nfox\njumps\nover\nthe\nlazy\ndog." + if Wrap(text, 5) != exp { + t.Fail() + } +} + +func TestWrapOneLine(t *testing.T) { + exp := "The quick brown fox jumps over the lazy dog." + if Wrap(text, 500) != exp { + t.Fail() + } +} diff --git a/Godeps/_workspace/src/github.com/magiconair/properties/.gitignore b/Godeps/_workspace/src/github.com/magiconair/properties/.gitignore new file mode 100644 index 00000000..0e379c52 --- /dev/null +++ b/Godeps/_workspace/src/github.com/magiconair/properties/.gitignore @@ -0,0 +1,2 @@ +*.sublime-project +*.sublime-workspace diff --git a/Godeps/_workspace/src/github.com/magiconair/properties/.travis.yml b/Godeps/_workspace/src/github.com/magiconair/properties/.travis.yml new file mode 100644 index 00000000..407127ca --- /dev/null +++ b/Godeps/_workspace/src/github.com/magiconair/properties/.travis.yml @@ -0,0 +1,5 @@ +language: go +go: + - release +install: go get gopkg.in/check.v1 + diff --git a/Godeps/_workspace/src/github.com/magiconair/properties/LICENSE b/Godeps/_workspace/src/github.com/magiconair/properties/LICENSE new file mode 100644 index 00000000..7eab43b6 --- /dev/null +++ b/Godeps/_workspace/src/github.com/magiconair/properties/LICENSE @@ -0,0 +1,25 @@ +goproperties - properties file decoder for Go + +Copyright (c) 2013-2014 - Frank Schroeder + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Godeps/_workspace/src/github.com/magiconair/properties/README.md b/Godeps/_workspace/src/github.com/magiconair/properties/README.md new file mode 100644 index 00000000..3cb834cf --- /dev/null +++ b/Godeps/_workspace/src/github.com/magiconair/properties/README.md @@ -0,0 +1,117 @@ +Overview [![Build Status](https://travis-ci.org/magiconair/properties.png?branch=master)](https://travis-ci.org/magiconair/properties) +======== + +properties is a Go library for reading and writing properties files. + +It supports reading from multiple files and Spring style recursive property +expansion of expressions like `${key}` to their corresponding value. +Value expressions can refer to other keys like in `${key}` or to +environment variables like in `${USER}`. +Filenames can also contain environment variables like in +`/home/${USER}/myapp.properties`. + +Comments and the order of keys are preserved. Comments can be modified +and can be written to the output. + +The properties library supports both ISO-8859-1 and UTF-8 encoded data. + +Starting from version 1.3.0 the behavior of the MustXXX() functions is +configurable by providing a custom `ErrorHandler` function. The default has +changed from `panic` to `log.Fatal` but this is configurable and custom +error handling functions can be provided. See the package documentation for +details. + +Getting Started +--------------- + +```go +import "github.com/magiconair/properties" + +func main() { + p := properties.MustLoadFile("${HOME}/config.properties", properties.UTF8) + host := p.MustGetString("host") + port := p.GetInt("port", 8080) +} + +``` + +Read the full documentation on [GoDoc](https://godoc.org/github.com/magiconair/properties) [![GoDoc](https://godoc.org/github.com/magiconair/properties?status.png)](https://godoc.org/github.com/magiconair/properties) + +Installation and Upgrade +------------------------ + +``` +$ go get -u github.com/magiconair/properties +``` + +For testing and debugging you need the [go-check](https://github.com/go-check/check) library + +``` +$ go get -u gopkg.in/check.v1 +``` + +History +------- + +v1.5.2, 10 Apr 2015 +------------------- + * [Issue #3](https://github.com/magiconair/properties/issues/3): Don't print comments in [WriteComment()](http://godoc.org/github.com/magiconair/properties#Properties.WriteComment) if they are all empty + * Add clickable links to README + +v1.5.1, 08 Dec 2014 +------------------- + * Added [GetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.GetParsedDuration) and [MustGetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.MustGetParsedDuration) for values specified compatible with + [time.ParseDuration()](http://golang.org/pkg/time/#ParseDuration). + +v1.5.0, 18 Nov 2014 +------------------- + * Added support for single and multi-line comments (reading, writing and updating) + * The order of keys is now preserved + * Calling [Set()](http://godoc.org/github.com/magiconair/properties#Properties.Set) with an empty key now silently ignores the call and does not create a new entry + * Added a [MustSet()](http://godoc.org/github.com/magiconair/properties#Properties.MustSet) method + * Migrated test library from launchpad.net/gocheck to [gopkg.in/check.v1](http://gopkg.in/check.v1) + +v1.4.2, 15 Nov 2014 +------------------- + * [Issue #2](https://github.com/magiconair/properties/issues/2): Fixed goroutine leak in parser which created two lexers but cleaned up only one + +v1.4.1, 13 Nov 2014 +------------------- + * [Issue #1](https://github.com/magiconair/properties/issues/1): Fixed bug in Keys() method which returned an empty string + +v1.4.0, 23 Sep 2014 +------------------- + * Added [Keys()](http://godoc.org/github.com/magiconair/properties#Properties.Keys) to get the keys + * Added [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) and [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) to get a subset of the properties + +v1.3.0, 18 Mar 2014 +------------------- +* Added support for time.Duration +* Made MustXXX() failure behavior configurable (log.Fatal, panic, custom) +* Changed default of MustXXX() failure from panic to log.Fatal + +v1.2.0, 05 Mar 2014 +------------------- +* Added MustGet... functions +* Added support for int and uint with range checks on 32 bit platforms + +v1.1.0, 20 Jan 2014 +------------------- +* Renamed from goproperties to properties +* Added support for expansion of environment vars in + filenames and value expressions +* Fixed bug where value expressions were not at the + start of the string + +v1.0.0, 7 Jan 2014 +------------------ +* Initial release + +License +------- + +2 clause BSD license. See [LICENSE](https://github.com/magiconair/properties/blob/master/LICENSE) file for details. + +ToDo +---- +* Dump contents with passwords and secrets obscured diff --git a/Godeps/_workspace/src/github.com/magiconair/properties/benchmark_test.go b/Godeps/_workspace/src/github.com/magiconair/properties/benchmark_test.go new file mode 100644 index 00000000..b2019e10 --- /dev/null +++ b/Godeps/_workspace/src/github.com/magiconair/properties/benchmark_test.go @@ -0,0 +1,22 @@ +// Copyright 2013-2014 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package properties + +import ( + "fmt" + "testing" +) + +// Benchmarks the decoder by creating a property file with 1000 key/value pairs. +func BenchmarkLoad(b *testing.B) { + input := "" + for i := 0; i < 1000; i++ { + input += fmt.Sprintf("key%d=value%d\n", i, i) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + Load([]byte(input), ISO_8859_1) + } +} diff --git a/Godeps/_workspace/src/github.com/magiconair/properties/doc.go b/Godeps/_workspace/src/github.com/magiconair/properties/doc.go new file mode 100644 index 00000000..69cf2e8e --- /dev/null +++ b/Godeps/_workspace/src/github.com/magiconair/properties/doc.go @@ -0,0 +1,135 @@ +// Copyright 2013-2014 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package properties provides functions for reading and writing +// ISO-8859-1 and UTF-8 encoded .properties files and has +// support for recursive property expansion. +// +// Java properties files are ISO-8859-1 encoded and use Unicode +// literals for characters outside the ISO character set. Unicode +// literals can be used in UTF-8 encoded properties files but +// aren't necessary. +// +// To load a single properties file use MustLoadFile(): +// +// p := properties.MustLoadFile(filename, properties.UTF8) +// +// To load multiple properties files use MustLoadFiles() +// which loads the files in the given order and merges the +// result. Missing properties files can be ignored if the +// 'ignoreMissing' flag is set to true. +// +// Filenames can contain environment variables which are expanded +// before loading. +// +// f1 := "/etc/myapp/myapp.conf" +// f2 := "/home/${USER}/myapp.conf" +// p := MustLoadFiles([]string{f1, f2}, properties.UTF8, true) +// +// All of the different key/value delimiters ' ', ':' and '=' are +// supported as well as the comment characters '!' and '#' and +// multi-line values. +// +// ! this is a comment +// # and so is this +// +// # the following expressions are equal +// key value +// key=value +// key:value +// key = value +// key : value +// key = val\ +// ue +// +// Properties stores all comments preceding a key and provides +// GetComments() and SetComments() methods to retrieve and +// update them. The convenience functions GetComment() and +// SetComment() allow access to the last comment. The +// WriteComment() method writes properties files including +// the comments and with the keys in the original order. +// This can be used for sanitizing properties files. +// +// Property expansion is recursive and circular references +// and malformed expressions are not allowed and cause an +// error. Expansion of environment variables is supported. +// +// # standard property +// key = value +// +// # property expansion: key2 = value +// key2 = ${key} +// +// # recursive expansion: key3 = value +// key3 = ${key2} +// +// # circular reference (error) +// key = ${key} +// +// # malformed expression (error) +// key = ${ke +// +// # refers to the users' home dir +// home = ${HOME} +// +// # local key takes precendence over env var: u = foo +// USER = foo +// u = ${USER} +// +// The default property expansion format is ${key} but can be +// changed by setting different pre- and postfix values on the +// Properties object. +// +// p := properties.NewProperties() +// p.Prefix = "#[" +// p.Postfix = "]#" +// +// Properties provides convenience functions for getting typed +// values with default values if the key does not exist or the +// type conversion failed. +// +// # Returns true if the value is either "1", "on", "yes" or "true" +// # Returns false for every other value and the default value if +// # the key does not exist. +// v = p.GetBool("key", false) +// +// # Returns the value if the key exists and the format conversion +// # was successful. Otherwise, the default value is returned. +// v = p.GetInt64("key", 999) +// v = p.GetUint64("key", 999) +// v = p.GetFloat64("key", 123.0) +// v = p.GetString("key", "def") +// v = p.GetDuration("key", 999) +// +// Properties provides several MustXXX() convenience functions +// which will terminate the app if an error occurs. The behavior +// of the failure is configurable and the default is to call +// log.Fatal(err). To have the MustXXX() functions panic instead +// of logging the error set a different ErrorHandler before +// you use the Properties package. +// +// properties.ErrorHandler = properties.PanicHandler +// +// # Will panic instead of logging an error +// p := properties.MustLoadFile("config.properties") +// +// You can also provide your own ErrorHandler function. The only requirement +// is that the error handler function must exit after handling the error. +// +// properties.ErrorHandler = func(err error) { +// fmt.Println(err) +// os.Exit(1) +// } +// +// # Will write to stdout and then exit +// p := properties.MustLoadFile("config.properties") +// +// The following documents provide a description of the properties +// file format. +// +// http://en.wikipedia.org/wiki/.properties +// +// http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.Reader%29 +// +package properties diff --git a/Godeps/_workspace/src/github.com/magiconair/properties/example_test.go b/Godeps/_workspace/src/github.com/magiconair/properties/example_test.go new file mode 100644 index 00000000..38bf04f5 --- /dev/null +++ b/Godeps/_workspace/src/github.com/magiconair/properties/example_test.go @@ -0,0 +1,93 @@ +// Copyright 2013-2014 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package properties + +import ( + "fmt" + "log" +) + +func ExampleLoad_iso88591() { + buf := []byte("key = ISO-8859-1 value with unicode literal \\u2318 and umlaut \xE4") // 0xE4 == ä + p, _ := Load(buf, ISO_8859_1) + v, ok := p.Get("key") + fmt.Println(ok) + fmt.Println(v) + // Output: + // true + // ISO-8859-1 value with unicode literal ⌘ and umlaut ä +} + +func ExampleLoad_utf8() { + p, _ := Load([]byte("key = UTF-8 value with unicode character ⌘ and umlaut ä"), UTF8) + v, ok := p.Get("key") + fmt.Println(ok) + fmt.Println(v) + // Output: + // true + // UTF-8 value with unicode character ⌘ and umlaut ä +} + +func ExampleProperties_GetBool() { + var input = ` + key=1 + key2=On + key3=YES + key4=true` + p, _ := Load([]byte(input), ISO_8859_1) + fmt.Println(p.GetBool("key", false)) + fmt.Println(p.GetBool("key2", false)) + fmt.Println(p.GetBool("key3", false)) + fmt.Println(p.GetBool("key4", false)) + fmt.Println(p.GetBool("keyX", false)) + // Output: + // true + // true + // true + // true + // false +} + +func ExampleProperties_GetString() { + p, _ := Load([]byte("key=value"), ISO_8859_1) + v := p.GetString("another key", "default value") + fmt.Println(v) + // Output: + // default value +} + +func Example() { + // Decode some key/value pairs with expressions + p, err := Load([]byte("key=value\nkey2=${key}"), ISO_8859_1) + if err != nil { + log.Fatal(err) + } + + // Get a valid key + if v, ok := p.Get("key"); ok { + fmt.Println(v) + } + + // Get an invalid key + if _, ok := p.Get("does not exist"); !ok { + fmt.Println("invalid key") + } + + // Get a key with a default value + v := p.GetString("does not exist", "some value") + fmt.Println(v) + + // Dump the expanded key/value pairs of the Properties + fmt.Println("Expanded key/value pairs") + fmt.Println(p) + + // Output: + // value + // invalid key + // some value + // Expanded key/value pairs + // key = value + // key2 = value +} diff --git a/Godeps/_workspace/src/github.com/magiconair/properties/lex.go b/Godeps/_workspace/src/github.com/magiconair/properties/lex.go new file mode 100644 index 00000000..1ae7a45d --- /dev/null +++ b/Godeps/_workspace/src/github.com/magiconair/properties/lex.go @@ -0,0 +1,409 @@ +// Copyright 2013-2014 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Parts of the lexer are from the template/text/parser package +// For these parts the following applies: +// +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file of the go 1.2 +// distribution. + +package properties + +import ( + "fmt" + "strconv" + "strings" + "unicode/utf8" +) + +// item represents a token or text string returned from the scanner. +type item struct { + typ itemType // The type of this item. + pos int // The starting position, in bytes, of this item in the input string. + val string // The value of this item. +} + +func (i item) String() string { + switch { + case i.typ == itemEOF: + return "EOF" + case i.typ == itemError: + return i.val + case len(i.val) > 10: + return fmt.Sprintf("%.10q...", i.val) + } + return fmt.Sprintf("%q", i.val) +} + +// itemType identifies the type of lex items. +type itemType int + +const ( + itemError itemType = iota // error occurred; value is text of error + itemEOF + itemKey // a key + itemValue // a value + itemComment // a comment +) + +// defines a constant for EOF +const eof = -1 + +// permitted whitespace characters space, FF and TAB +const whitespace = " \f\t" + +// stateFn represents the state of the scanner as a function that returns the next state. +type stateFn func(*lexer) stateFn + +// lexer holds the state of the scanner. +type lexer struct { + input string // the string being scanned + state stateFn // the next lexing function to enter + pos int // current position in the input + start int // start position of this item + width int // width of last rune read from input + lastPos int // position of most recent item returned by nextItem + runes []rune // scanned runes for this item + items chan item // channel of scanned items +} + +// next returns the next rune in the input. +func (l *lexer) next() rune { + if int(l.pos) >= len(l.input) { + l.width = 0 + return eof + } + r, w := utf8.DecodeRuneInString(l.input[l.pos:]) + l.width = w + l.pos += l.width + return r +} + +// peek returns but does not consume the next rune in the input. +func (l *lexer) peek() rune { + r := l.next() + l.backup() + return r +} + +// backup steps back one rune. Can only be called once per call of next. +func (l *lexer) backup() { + l.pos -= l.width +} + +// emit passes an item back to the client. +func (l *lexer) emit(t itemType) { + item := item{t, l.start, string(l.runes)} + l.items <- item + l.start = l.pos + l.runes = l.runes[:0] +} + +// ignore skips over the pending input before this point. +func (l *lexer) ignore() { + l.start = l.pos +} + +// appends the rune to the current value +func (l *lexer) appendRune(r rune) { + l.runes = append(l.runes, r) +} + +// accept consumes the next rune if it's from the valid set. +func (l *lexer) accept(valid string) bool { + if strings.IndexRune(valid, l.next()) >= 0 { + return true + } + l.backup() + return false +} + +// acceptRun consumes a run of runes from the valid set. +func (l *lexer) acceptRun(valid string) { + for strings.IndexRune(valid, l.next()) >= 0 { + } + l.backup() +} + +// acceptRunUntil consumes a run of runes up to a terminator. +func (l *lexer) acceptRunUntil(term rune) { + for term != l.next() { + } + l.backup() +} + +// hasText returns true if the current parsed text is not empty. +func (l *lexer) isNotEmpty() bool { + return l.pos > l.start +} + +// lineNumber reports which line we're on, based on the position of +// the previous item returned by nextItem. Doing it this way +// means we don't have to worry about peek double counting. +func (l *lexer) lineNumber() int { + return 1 + strings.Count(l.input[:l.lastPos], "\n") +} + +// errorf returns an error token and terminates the scan by passing +// back a nil pointer that will be the next state, terminating l.nextItem. +func (l *lexer) errorf(format string, args ...interface{}) stateFn { + l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)} + return nil +} + +// nextItem returns the next item from the input. +func (l *lexer) nextItem() item { + item := <-l.items + l.lastPos = item.pos + return item +} + +// lex creates a new scanner for the input string. +func lex(input string) *lexer { + l := &lexer{ + input: input, + items: make(chan item), + runes: make([]rune, 0, 32), + } + go l.run() + return l +} + +// run runs the state machine for the lexer. +func (l *lexer) run() { + for l.state = lexBeforeKey(l); l.state != nil; { + l.state = l.state(l) + } +} + +// state functions + +// lexBeforeKey scans until a key begins. +func lexBeforeKey(l *lexer) stateFn { + switch r := l.next(); { + case isEOF(r): + l.emit(itemEOF) + return nil + + case isEOL(r): + l.ignore() + return lexBeforeKey + + case isComment(r): + return lexComment + + case isWhitespace(r): + l.acceptRun(whitespace) + l.ignore() + return lexKey + + default: + l.backup() + return lexKey + } +} + +// lexComment scans a comment line. The comment character has already been scanned. +func lexComment(l *lexer) stateFn { + l.acceptRun(whitespace) + l.ignore() + for { + switch r := l.next(); { + case isEOF(r): + l.ignore() + l.emit(itemEOF) + return nil + case isEOL(r): + l.emit(itemComment) + return lexBeforeKey + default: + l.appendRune(r) + } + } +} + +// lexKey scans the key up to a delimiter +func lexKey(l *lexer) stateFn { + var r rune + +Loop: + for { + switch r = l.next(); { + + case isEscape(r): + err := l.scanEscapeSequence() + if err != nil { + return l.errorf(err.Error()) + } + + case isEndOfKey(r): + l.backup() + break Loop + + case isEOF(r): + break Loop + + default: + l.appendRune(r) + } + } + + if len(l.runes) > 0 { + l.emit(itemKey) + } + + if isEOF(r) { + l.emit(itemEOF) + return nil + } + + return lexBeforeValue +} + +// lexBeforeValue scans the delimiter between key and value. +// Leading and trailing whitespace is ignored. +// We expect to be just after the key. +func lexBeforeValue(l *lexer) stateFn { + l.acceptRun(whitespace) + l.accept(":=") + l.acceptRun(whitespace) + l.ignore() + return lexValue +} + +// lexValue scans text until the end of the line. We expect to be just after the delimiter. +func lexValue(l *lexer) stateFn { + for { + switch r := l.next(); { + case isEscape(r): + r := l.peek() + if isEOL(r) { + l.next() + l.acceptRun(whitespace) + } else { + err := l.scanEscapeSequence() + if err != nil { + return l.errorf(err.Error()) + } + } + + case isEOL(r): + l.emit(itemValue) + l.ignore() + return lexBeforeKey + + case isEOF(r): + l.emit(itemValue) + l.emit(itemEOF) + return nil + + default: + l.appendRune(r) + } + } +} + +// scanEscapeSequence scans either one of the escaped characters +// or a unicode literal. We expect to be after the escape character. +func (l *lexer) scanEscapeSequence() error { + switch r := l.next(); { + + case isEscapedCharacter(r): + l.appendRune(decodeEscapedCharacter(r)) + return nil + + case atUnicodeLiteral(r): + return l.scanUnicodeLiteral() + + case isEOF(r): + return fmt.Errorf("premature EOF") + + // silently drop the escape character and append the rune as is + default: + l.appendRune(r) + return nil + } +} + +// scans a unicode literal in the form \uXXXX. We expect to be after the \u. +func (l *lexer) scanUnicodeLiteral() error { + // scan the digits + d := make([]rune, 4) + for i := 0; i < 4; i++ { + d[i] = l.next() + if d[i] == eof || !strings.ContainsRune("0123456789abcdefABCDEF", d[i]) { + return fmt.Errorf("invalid unicode literal") + } + } + + // decode the digits into a rune + r, err := strconv.ParseInt(string(d), 16, 0) + if err != nil { + return err + } + + l.appendRune(rune(r)) + return nil +} + +// decodeEscapedCharacter returns the unescaped rune. We expect to be after the escape character. +func decodeEscapedCharacter(r rune) rune { + switch r { + case 'f': + return '\f' + case 'n': + return '\n' + case 'r': + return '\r' + case 't': + return '\t' + default: + return r + } +} + +// atUnicodeLiteral reports whether we are at a unicode literal. +// The escape character has already been consumed. +func atUnicodeLiteral(r rune) bool { + return r == 'u' +} + +// isComment reports whether we are at the start of a comment. +func isComment(r rune) bool { + return r == '#' || r == '!' +} + +// isEndOfKey reports whether the rune terminates the current key. +func isEndOfKey(r rune) bool { + return strings.ContainsRune(" \f\t\r\n:=", r) +} + +// isEOF reports whether we are at EOF. +func isEOF(r rune) bool { + return r == eof +} + +// isEOL reports whether we are at a new line character. +func isEOL(r rune) bool { + return r == '\n' || r == '\r' +} + +// isEscape reports whether the rune is the escape character which +// prefixes unicode literals and other escaped characters. +func isEscape(r rune) bool { + return r == '\\' +} + +// isEscapedCharacter reports whether we are at one of the characters that need escaping. +// The escape character has already been consumed. +func isEscapedCharacter(r rune) bool { + return strings.ContainsRune(" :=fnrt", r) +} + +// isWhitespace reports whether the rune is a whitespace character. +func isWhitespace(r rune) bool { + return strings.ContainsRune(whitespace, r) +} diff --git a/Godeps/_workspace/src/github.com/magiconair/properties/load.go b/Godeps/_workspace/src/github.com/magiconair/properties/load.go new file mode 100644 index 00000000..431d4622 --- /dev/null +++ b/Godeps/_workspace/src/github.com/magiconair/properties/load.go @@ -0,0 +1,124 @@ +// Copyright 2013-2014 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package properties + +import ( + "fmt" + "io/ioutil" + "os" +) + +// Encoding specifies encoding of the input data. +type Encoding uint + +const ( + // UTF8 interprets the input data as UTF-8. + UTF8 Encoding = 1 << iota + + // ISO_8859_1 interprets the input data as ISO-8859-1. + ISO_8859_1 +) + +// Load reads a buffer into a Properties struct. +func Load(buf []byte, enc Encoding) (*Properties, error) { + return loadBuf(buf, enc) +} + +// LoadFile reads a file into a Properties struct. +func LoadFile(filename string, enc Encoding) (*Properties, error) { + return loadFiles([]string{filename}, enc, false) +} + +// LoadFiles reads multiple files in the given order into +// a Properties struct. If 'ignoreMissing' is true then +// non-existent files will not be reported as error. +func LoadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error) { + return loadFiles(filenames, enc, ignoreMissing) +} + +// MustLoadFile reads a file into a Properties struct and +// panics on error. +func MustLoadFile(filename string, enc Encoding) *Properties { + return mustLoadFiles([]string{filename}, enc, false) +} + +// MustLoadFiles reads multiple files in the given order into +// a Properties struct and panics on error. If 'ignoreMissing' +// is true then non-existent files will not be reported as error. +func MustLoadFiles(filenames []string, enc Encoding, ignoreMissing bool) *Properties { + return mustLoadFiles(filenames, enc, ignoreMissing) +} + +// ---------------------------------------------------------------------------- + +func loadBuf(buf []byte, enc Encoding) (*Properties, error) { + p, err := parse(convert(buf, enc)) + if err != nil { + return nil, err + } + + return p, p.check() +} + +func loadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error) { + buff := make([]byte, 0, 4096) + + for _, filename := range filenames { + f, err := expandFilename(filename) + if err != nil { + return nil, err + } + + buf, err := ioutil.ReadFile(f) + if err != nil { + if ignoreMissing && os.IsNotExist(err) { + // TODO(frank): should we log that we are skipping the file? + continue + } + return nil, err + } + + // concatenate the buffers and add a new line in case + // the previous file didn't end with a new line + buff = append(append(buff, buf...), '\n') + } + + return loadBuf(buff, enc) +} + +func mustLoadFiles(filenames []string, enc Encoding, ignoreMissing bool) *Properties { + p, err := loadFiles(filenames, enc, ignoreMissing) + if err != nil { + ErrorHandler(err) + } + return p +} + +// expandFilename expands ${ENV_VAR} expressions in a filename. +// If the environment variable does not exist then it will be replaced +// with an empty string. Malformed expressions like "${ENV_VAR" will +// be reported as error. +func expandFilename(filename string) (string, error) { + return expand(filename, make(map[string]bool), "${", "}", make(map[string]string)) +} + +// Interprets a byte buffer either as an ISO-8859-1 or UTF-8 encoded string. +// For ISO-8859-1 we can convert each byte straight into a rune since the +// first 256 unicode code points cover ISO-8859-1. +func convert(buf []byte, enc Encoding) string { + switch enc { + case UTF8: + return string(buf) + case ISO_8859_1: + runes := make([]rune, len(buf)) + for i, b := range buf { + runes[i] = rune(b) + } + return string(runes) + default: + ErrorHandler(fmt.Errorf("unsupported encoding %v", enc)) + } + panic("ErrorHandler should exit") +} diff --git a/Godeps/_workspace/src/github.com/magiconair/properties/load_test.go b/Godeps/_workspace/src/github.com/magiconair/properties/load_test.go new file mode 100644 index 00000000..9d1e3b62 --- /dev/null +++ b/Godeps/_workspace/src/github.com/magiconair/properties/load_test.go @@ -0,0 +1,137 @@ +// Copyright 2013-2014 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package properties + +import ( + "fmt" + "io/ioutil" + "os" + "strings" + + . "gopkg.in/check.v1" +) + +type LoadSuite struct { + tempFiles []string +} + +var ( + _ = Suite(&LoadSuite{}) +) + +// ---------------------------------------------------------------------------- + +func (s *LoadSuite) TestLoadFailsWithNotExistingFile(c *C) { + _, err := LoadFile("doesnotexist.properties", ISO_8859_1) + c.Assert(err, NotNil) + c.Assert(err, ErrorMatches, "open.*no such file or directory") +} + +// ---------------------------------------------------------------------------- + +func (s *LoadSuite) TestLoadFilesFailsOnNotExistingFile(c *C) { + _, err := LoadFiles([]string{"doesnotexist.properties"}, ISO_8859_1, false) + c.Assert(err, NotNil) + c.Assert(err, ErrorMatches, "open.*no such file or directory") +} + +// ---------------------------------------------------------------------------- + +func (s *LoadSuite) TestLoadFilesDoesNotFailOnNotExistingFileAndIgnoreMissing(c *C) { + p, err := LoadFiles([]string{"doesnotexist.properties"}, ISO_8859_1, true) + c.Assert(err, IsNil) + c.Assert(p.Len(), Equals, 0) +} + +// ---------------------------------------------------------------------------- + +func (s *LoadSuite) TestLoad(c *C) { + filename := s.makeFile(c, "key=value") + p := MustLoadFile(filename, ISO_8859_1) + + c.Assert(p.Len(), Equals, 1) + assertKeyValues(c, "", p, "key", "value") +} + +// ---------------------------------------------------------------------------- + +func (s *LoadSuite) TestLoadFiles(c *C) { + filename := s.makeFile(c, "key=value") + filename2 := s.makeFile(c, "key2=value2") + p := MustLoadFiles([]string{filename, filename2}, ISO_8859_1, false) + assertKeyValues(c, "", p, "key", "value", "key2", "value2") +} + +// ---------------------------------------------------------------------------- + +func (s *LoadSuite) TestLoadExpandedFile(c *C) { + filename := s.makeFilePrefix(c, os.Getenv("USER"), "key=value") + filename = strings.Replace(filename, os.Getenv("USER"), "${USER}", -1) + p := MustLoadFile(filename, ISO_8859_1) + assertKeyValues(c, "", p, "key", "value") +} + +// ---------------------------------------------------------------------------- + +func (s *LoadSuite) TestLoadFilesAndIgnoreMissing(c *C) { + filename := s.makeFile(c, "key=value") + filename2 := s.makeFile(c, "key2=value2") + p := MustLoadFiles([]string{filename, filename + "foo", filename2, filename2 + "foo"}, ISO_8859_1, true) + assertKeyValues(c, "", p, "key", "value", "key2", "value2") +} + +// ---------------------------------------------------------------------------- + +func (s *LoadSuite) SetUpSuite(c *C) { + s.tempFiles = make([]string, 0) +} + +// ---------------------------------------------------------------------------- + +func (s *LoadSuite) TearDownSuite(c *C) { + for _, path := range s.tempFiles { + err := os.Remove(path) + if err != nil { + fmt.Printf("os.Remove: %v", err) + } + } +} + +// ---------------------------------------------------------------------------- + +func (s *LoadSuite) makeFile(c *C, data string) string { + return s.makeFilePrefix(c, "properties", data) +} + +// ---------------------------------------------------------------------------- + +func (s *LoadSuite) makeFilePrefix(c *C, prefix, data string) string { + f, err := ioutil.TempFile("", prefix) + if err != nil { + fmt.Printf("ioutil.TempFile: %v", err) + c.FailNow() + } + + // remember the temp file so that we can remove it later + s.tempFiles = append(s.tempFiles, f.Name()) + + n, err := fmt.Fprint(f, data) + if err != nil { + fmt.Printf("fmt.Fprintln: %v", err) + c.FailNow() + } + if n != len(data) { + fmt.Printf("Data size mismatch. expected=%d wrote=%d\n", len(data), n) + c.FailNow() + } + + err = f.Close() + if err != nil { + fmt.Printf("f.Close: %v", err) + c.FailNow() + } + + return f.Name() +} diff --git a/Godeps/_workspace/src/github.com/magiconair/properties/parser.go b/Godeps/_workspace/src/github.com/magiconair/properties/parser.go new file mode 100644 index 00000000..bb71fb94 --- /dev/null +++ b/Godeps/_workspace/src/github.com/magiconair/properties/parser.go @@ -0,0 +1,95 @@ +// Copyright 2013-2014 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package properties + +import ( + "fmt" + "runtime" +) + +type parser struct { + lex *lexer +} + +func parse(input string) (properties *Properties, err error) { + p := &parser{lex: lex(input)} + defer p.recover(&err) + + properties = NewProperties() + key := "" + comments := []string{} + + for { + token := p.expectOneOf(itemComment, itemKey, itemEOF) + switch token.typ { + case itemEOF: + goto done + case itemComment: + comments = append(comments, token.val) + continue + case itemKey: + key = token.val + if _, ok := properties.m[key]; !ok { + properties.k = append(properties.k, key) + } + } + + token = p.expectOneOf(itemValue, itemEOF) + if len(comments) > 0 { + properties.c[key] = comments + comments = []string{} + } + switch token.typ { + case itemEOF: + properties.m[key] = "" + goto done + case itemValue: + properties.m[key] = token.val + } + } + +done: + return properties, nil +} + +func (p *parser) errorf(format string, args ...interface{}) { + format = fmt.Sprintf("properties: Line %d: %s", p.lex.lineNumber(), format) + panic(fmt.Errorf(format, args...)) +} + +func (p *parser) expect(expected itemType) (token item) { + token = p.lex.nextItem() + if token.typ != expected { + p.unexpected(token) + } + return token +} + +func (p *parser) expectOneOf(expected ...itemType) (token item) { + token = p.lex.nextItem() + for _, v := range expected { + if token.typ == v { + return token + } + } + p.unexpected(token) + panic("unexpected token") +} + +func (p *parser) unexpected(token item) { + p.errorf(token.String()) +} + +// recover is the handler that turns panics into returns from the top level of Parse. +func (p *parser) recover(errp *error) { + e := recover() + if e != nil { + if _, ok := e.(runtime.Error); ok { + panic(e) + } + *errp = e.(error) + } + return +} diff --git a/Godeps/_workspace/src/github.com/magiconair/properties/properties.go b/Godeps/_workspace/src/github.com/magiconair/properties/properties.go new file mode 100644 index 00000000..33c108c1 --- /dev/null +++ b/Godeps/_workspace/src/github.com/magiconair/properties/properties.go @@ -0,0 +1,698 @@ +// Copyright 2013-2014 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package properties + +// BUG(frank): Set() does not check for invalid unicode literals since this is currently handled by the lexer. +// BUG(frank): Write() does not allow to configure the newline character. Therefore, on Windows LF is used. + +import ( + "fmt" + "io" + "log" + "os" + "regexp" + "strconv" + "strings" + "time" + "unicode/utf8" +) + +// ErrorHandlerFunc defines the type of function which handles failures +// of the MustXXX() functions. An error handler function must exit +// the application after handling the error. +type ErrorHandlerFunc func(error) + +// ErrorHandler is the function which handles failures of the MustXXX() +// functions. The default is LogFatalHandler. +var ErrorHandler = LogFatalHandler + +// LogFatalHandler handles the error by logging a fatal error and exiting. +func LogFatalHandler(err error) { + log.Fatal(err) +} + +// PanicHandler handles the error by panicking. +func PanicHandler(err error) { + panic(err) +} + +// ----------------------------------------------------------------------------- + +// A Properties contains the key/value pairs from the properties input. +// All values are stored in unexpanded form and are expanded at runtime +type Properties struct { + // Pre-/Postfix for property expansion. + Prefix string + Postfix string + + // Stores the key/value pairs + m map[string]string + + // Stores the comments per key. + c map[string][]string + + // Stores the keys in order of appearance. + k []string +} + +// NewProperties creates a new Properties struct with the default +// configuration for "${key}" expressions. +func NewProperties() *Properties { + return &Properties{ + Prefix: "${", + Postfix: "}", + m: map[string]string{}, + c: map[string][]string{}, + k: []string{}, + } +} + +// Get returns the expanded value for the given key if exists. +// Otherwise, ok is false. +func (p *Properties) Get(key string) (value string, ok bool) { + v, ok := p.m[key] + if !ok { + return "", false + } + + expanded, err := p.expand(v) + + // we guarantee that the expanded value is free of + // circular references and malformed expressions + // so we panic if we still get an error here. + if err != nil { + ErrorHandler(fmt.Errorf("%s in %q", err, key+" = "+v)) + } + + return expanded, true +} + +// MustGet returns the expanded value for the given key if exists. +// Otherwise, it panics. +func (p *Properties) MustGet(key string) string { + if v, ok := p.Get(key); ok { + return v + } + ErrorHandler(invalidKeyError(key)) + panic("ErrorHandler should exit") +} + +// ---------------------------------------------------------------------------- + +// ClearComments removes the comments for all keys. +func (p *Properties) ClearComments() { + p.c = map[string][]string{} +} + +// ---------------------------------------------------------------------------- + +// GetComment returns the last comment before the given key or an empty string. +func (p *Properties) GetComment(key string) string { + comments, ok := p.c[key] + if !ok || len(comments) == 0 { + return "" + } + return comments[len(comments)-1] +} + +// ---------------------------------------------------------------------------- + +// GetComments returns all comments that appeared before the given key or nil. +func (p *Properties) GetComments(key string) []string { + if comments, ok := p.c[key]; ok { + return comments + } + return nil +} + +// ---------------------------------------------------------------------------- + +// SetComment sets the comment for the key. +func (p *Properties) SetComment(key, comment string) { + p.c[key] = []string{comment} +} + +// ---------------------------------------------------------------------------- + +// SetComments sets the comments for the key. If the comments are nil then +// all comments for this key are deleted. +func (p *Properties) SetComments(key string, comments []string) { + if comments == nil { + delete(p.c, key) + return + } + p.c[key] = comments +} + +// ---------------------------------------------------------------------------- + +// GetBool checks if the expanded value is one of '1', 'yes', +// 'true' or 'on' if the key exists. The comparison is case-insensitive. +// If the key does not exist the default value is returned. +func (p *Properties) GetBool(key string, def bool) bool { + v, err := p.getBool(key) + if err != nil { + return def + } + return v +} + +// MustGetBool checks if the expanded value is one of '1', 'yes', +// 'true' or 'on' if the key exists. The comparison is case-insensitive. +// If the key does not exist the function panics. +func (p *Properties) MustGetBool(key string) bool { + v, err := p.getBool(key) + if err != nil { + ErrorHandler(err) + } + return v +} + +func (p *Properties) getBool(key string) (value bool, err error) { + if v, ok := p.Get(key); ok { + v = strings.ToLower(v) + return v == "1" || v == "true" || v == "yes" || v == "on", nil + } + return false, invalidKeyError(key) +} + +// ---------------------------------------------------------------------------- + +// GetDuration parses the expanded value as an time.Duration (in ns) if the +// key exists. If key does not exist or the value cannot be parsed the default +// value is returned. In almost all cases you want to use GetParsedDuration(). +func (p *Properties) GetDuration(key string, def time.Duration) time.Duration { + v, err := p.getInt64(key) + if err != nil { + return def + } + return time.Duration(v) +} + +// MustGetDuration parses the expanded value as an time.Duration (in ns) if +// the key exists. If key does not exist or the value cannot be parsed the +// function panics. In almost all cases you want to use MustGetParsedDuration(). +func (p *Properties) MustGetDuration(key string) time.Duration { + v, err := p.getInt64(key) + if err != nil { + ErrorHandler(err) + } + return time.Duration(v) +} + +// ---------------------------------------------------------------------------- + +// GetParsedDuration parses the expanded value with time.ParseDuration() if the key exists. +// If key does not exist or the value cannot be parsed the default +// value is returned. +func (p *Properties) GetParsedDuration(key string, def time.Duration) time.Duration { + s, ok := p.Get(key) + if !ok { + return def + } + v, err := time.ParseDuration(s) + if err != nil { + return def + } + return v +} + +// MustGetParsedDuration parses the expanded value with time.ParseDuration() if the key exists. +// If key does not exist or the value cannot be parsed the function panics. +func (p *Properties) MustGetParsedDuration(key string) time.Duration { + s, ok := p.Get(key) + if !ok { + ErrorHandler(invalidKeyError(key)) + } + v, err := time.ParseDuration(s) + if err != nil { + ErrorHandler(err) + } + return v +} + +// ---------------------------------------------------------------------------- + +// GetFloat64 parses the expanded value as a float64 if the key exists. +// If key does not exist or the value cannot be parsed the default +// value is returned. +func (p *Properties) GetFloat64(key string, def float64) float64 { + v, err := p.getFloat64(key) + if err != nil { + return def + } + return v +} + +// MustGetFloat64 parses the expanded value as a float64 if the key exists. +// If key does not exist or the value cannot be parsed the function panics. +func (p *Properties) MustGetFloat64(key string) float64 { + v, err := p.getFloat64(key) + if err != nil { + ErrorHandler(err) + } + return v +} + +func (p *Properties) getFloat64(key string) (value float64, err error) { + if v, ok := p.Get(key); ok { + value, err = strconv.ParseFloat(v, 64) + if err != nil { + return 0, err + } + return value, nil + } + return 0, invalidKeyError(key) +} + +// ---------------------------------------------------------------------------- + +// GetInt parses the expanded value as an int if the key exists. +// If key does not exist or the value cannot be parsed the default +// value is returned. If the value does not fit into an int the +// function panics with an out of range error. +func (p *Properties) GetInt(key string, def int) int { + v, err := p.getInt64(key) + if err != nil { + return def + } + return intRangeCheck(key, v) +} + +// MustGetInt parses the expanded value as an int if the key exists. +// If key does not exist or the value cannot be parsed the function panics. +// If the value does not fit into an int the function panics with +// an out of range error. +func (p *Properties) MustGetInt(key string) int { + v, err := p.getInt64(key) + if err != nil { + ErrorHandler(err) + } + return intRangeCheck(key, v) +} + +// ---------------------------------------------------------------------------- + +// GetInt64 parses the expanded value as an int64 if the key exists. +// If key does not exist or the value cannot be parsed the default +// value is returned. +func (p *Properties) GetInt64(key string, def int64) int64 { + v, err := p.getInt64(key) + if err != nil { + return def + } + return v +} + +// MustGetInt64 parses the expanded value as an int if the key exists. +// If key does not exist or the value cannot be parsed the function panics. +func (p *Properties) MustGetInt64(key string) int64 { + v, err := p.getInt64(key) + if err != nil { + ErrorHandler(err) + } + return v +} + +func (p *Properties) getInt64(key string) (value int64, err error) { + if v, ok := p.Get(key); ok { + value, err = strconv.ParseInt(v, 10, 64) + if err != nil { + return 0, err + } + return value, nil + } + return 0, invalidKeyError(key) +} + +// ---------------------------------------------------------------------------- + +// GetUint parses the expanded value as an uint if the key exists. +// If key does not exist or the value cannot be parsed the default +// value is returned. If the value does not fit into an int the +// function panics with an out of range error. +func (p *Properties) GetUint(key string, def uint) uint { + v, err := p.getUint64(key) + if err != nil { + return def + } + return uintRangeCheck(key, v) +} + +// MustGetUint parses the expanded value as an int if the key exists. +// If key does not exist or the value cannot be parsed the function panics. +// If the value does not fit into an int the function panics with +// an out of range error. +func (p *Properties) MustGetUint(key string) uint { + v, err := p.getUint64(key) + if err != nil { + ErrorHandler(err) + } + return uintRangeCheck(key, v) +} + +// ---------------------------------------------------------------------------- + +// GetUint64 parses the expanded value as an uint64 if the key exists. +// If key does not exist or the value cannot be parsed the default +// value is returned. +func (p *Properties) GetUint64(key string, def uint64) uint64 { + v, err := p.getUint64(key) + if err != nil { + return def + } + return v +} + +// MustGetUint64 parses the expanded value as an int if the key exists. +// If key does not exist or the value cannot be parsed the function panics. +func (p *Properties) MustGetUint64(key string) uint64 { + v, err := p.getUint64(key) + if err != nil { + ErrorHandler(err) + } + return v +} + +func (p *Properties) getUint64(key string) (value uint64, err error) { + if v, ok := p.Get(key); ok { + value, err = strconv.ParseUint(v, 10, 64) + if err != nil { + return 0, err + } + return value, nil + } + return 0, invalidKeyError(key) +} + +// ---------------------------------------------------------------------------- + +// GetString returns the expanded value for the given key if exists or +// the default value otherwise. +func (p *Properties) GetString(key, def string) string { + if v, ok := p.Get(key); ok { + return v + } + return def +} + +// MustGetString returns the expanded value for the given key if exists or +// panics otherwise. +func (p *Properties) MustGetString(key string) string { + if v, ok := p.Get(key); ok { + return v + } + ErrorHandler(invalidKeyError(key)) + panic("ErrorHandler should exit") +} + +// ---------------------------------------------------------------------------- + +// Filter returns a new properties object which contains all properties +// for which the key matches the pattern. +func (p *Properties) Filter(pattern string) (*Properties, error) { + re, err := regexp.Compile(pattern) + if err != nil { + return nil, err + } + + return p.FilterRegexp(re), nil +} + +// FilterRegexp returns a new properties object which contains all properties +// for which the key matches the regular expression. +func (p *Properties) FilterRegexp(re *regexp.Regexp) *Properties { + pp := NewProperties() + for k, v := range p.m { + if re.MatchString(k) { + pp.Set(k, v) + } + } + return pp +} + +// FilterPrefix returns a new properties object which contains all properties +// for which the key starts with the prefix. +func (p *Properties) FilterPrefix(prefix string) *Properties { + pp := NewProperties() + for k, v := range p.m { + if strings.HasPrefix(k, prefix) { + pp.Set(k, v) + } + } + return pp +} + +// Len returns the number of keys. +func (p *Properties) Len() int { + return len(p.m) +} + +// Keys returns all keys in the same order as in the input. +func (p *Properties) Keys() []string { + keys := make([]string, len(p.k)) + for i, k := range p.k { + keys[i] = k + } + return keys +} + +// Set sets the property key to the corresponding value. +// If a value for key existed before then ok is true and prev +// contains the previous value. If the value contains a +// circular reference or a malformed expression then +// an error is returned. +// An empty key is silently ignored. +func (p *Properties) Set(key, value string) (prev string, ok bool, err error) { + if key == "" { + return "", false, nil + } + + // to check for a circular reference we temporarily need + // to set the new value. If there is an error then revert + // to the previous state. Only if all tests are successful + // then we add the key to the p.k list. + prev, ok = p.Get(key) + p.m[key] = value + + // now check for a circular reference + _, err = p.expand(value) + if err != nil { + + // revert to the previous state + if ok { + p.m[key] = prev + } else { + delete(p.m, key) + } + + return "", false, err + } + + if !ok { + p.k = append(p.k, key) + } + + return prev, ok, nil +} + +// MustSet sets the property key to the corresponding value. +// If a value for key existed before then ok is true and prev +// contains the previous value. An empty key is silently ignored. +func (p *Properties) MustSet(key, value string) (prev string, ok bool) { + prev, ok, err := p.Set(key, value) + if err != nil { + ErrorHandler(err) + } + return prev, ok +} + +// String returns a string of all expanded 'key = value' pairs. +func (p *Properties) String() string { + var s string + for _, key := range p.k { + value, _ := p.Get(key) + s = fmt.Sprintf("%s%s = %s\n", s, key, value) + } + return s +} + +// Write writes all unexpanded 'key = value' pairs to the given writer. +// Write returns the number of bytes written and any write error encountered. +func (p *Properties) Write(w io.Writer, enc Encoding) (n int, err error) { + return p.WriteComment(w, "", enc) +} + +// WriteComment writes all unexpanced 'key = value' pairs to the given writer. +// If prefix is not empty then comments are written with a blank line and the +// given prefix. The prefix should be either "# " or "! " to be compatible with +// the properties file format. Otherwise, the properties parser will not be +// able to read the file back in. It returns the number of bytes written and +// any write error encountered. +func (p *Properties) WriteComment(w io.Writer, prefix string, enc Encoding) (n int, err error) { + var x int + + for _, key := range p.k { + value := p.m[key] + + if prefix != "" { + if comments, ok := p.c[key]; ok { + // don't print comments if they are all empty + allEmpty := true + for _, c := range comments { + if c != "" { + allEmpty = false + break + } + } + + if !allEmpty { + // add a blank line between entries but not at the top + if len(comments) > 0 && n > 0 { + x, err = fmt.Fprintln(w) + if err != nil { + return + } + n += x + } + + for _, c := range comments { + x, err = fmt.Fprintf(w, "%s%s\n", prefix, encode(c, "", enc)) + if err != nil { + return + } + n += x + } + } + } + } + + x, err = fmt.Fprintf(w, "%s = %s\n", encode(key, " :", enc), encode(value, "", enc)) + if err != nil { + return + } + n += x + } + return +} + +// ---------------------------------------------------------------------------- + +// check expands all values and returns an error if a circular reference or +// a malformed expression was found. +func (p *Properties) check() error { + for _, value := range p.m { + if _, err := p.expand(value); err != nil { + return err + } + } + return nil +} + +func (p *Properties) expand(input string) (string, error) { + // no pre/postfix -> nothing to expand + if p.Prefix == "" && p.Postfix == "" { + return input, nil + } + + return expand(input, make(map[string]bool), p.Prefix, p.Postfix, p.m) +} + +// expand recursively expands expressions of '(prefix)key(postfix)' to their corresponding values. +// The function keeps track of the keys that were already expanded and stops if it +// detects a circular reference or a malformed expression of the form '(prefix)key'. +func expand(s string, keys map[string]bool, prefix, postfix string, values map[string]string) (string, error) { + start := strings.Index(s, prefix) + if start == -1 { + return s, nil + } + + keyStart := start + len(prefix) + keyLen := strings.Index(s[keyStart:], postfix) + if keyLen == -1 { + return "", fmt.Errorf("malformed expression") + } + + end := keyStart + keyLen + len(postfix) - 1 + key := s[keyStart : keyStart+keyLen] + + // fmt.Printf("s:%q pp:%q start:%d end:%d keyStart:%d keyLen:%d key:%q\n", s, prefix + "..." + postfix, start, end, keyStart, keyLen, key) + + if _, ok := keys[key]; ok { + return "", fmt.Errorf("circular reference") + } + + val, ok := values[key] + if !ok { + val = os.Getenv(key) + } + + // remember that we've seen the key + keys[key] = true + + return expand(s[:start]+val+s[end+1:], keys, prefix, postfix, values) +} + +// encode encodes a UTF-8 string to ISO-8859-1 and escapes some characters. +func encode(s string, special string, enc Encoding) string { + switch enc { + case UTF8: + return encodeUtf8(s, special) + case ISO_8859_1: + return encodeIso(s, special) + default: + panic(fmt.Sprintf("unsupported encoding %v", enc)) + } +} + +func encodeUtf8(s string, special string) string { + v := "" + for pos := 0; pos < len(s); { + r, w := utf8.DecodeRuneInString(s[pos:]) + pos += w + v += escape(r, special) + } + return v +} + +func encodeIso(s string, special string) string { + var r rune + var w int + var v string + for pos := 0; pos < len(s); { + switch r, w = utf8.DecodeRuneInString(s[pos:]); { + case r < 1<<8: // single byte rune -> escape special chars only + v += escape(r, special) + case r < 1<<16: // two byte rune -> unicode literal + v += fmt.Sprintf("\\u%04x", r) + default: // more than two bytes per rune -> can't encode + v += "?" + } + pos += w + } + return v +} + +func escape(r rune, special string) string { + switch r { + case '\f': + return "\\f" + case '\n': + return "\\n" + case '\r': + return "\\r" + case '\t': + return "\\t" + default: + if strings.ContainsRune(special, r) { + return "\\" + string(r) + } + return string(r) + } +} + +func invalidKeyError(key string) error { + return fmt.Errorf("unknown property: %s", key) +} diff --git a/Godeps/_workspace/src/github.com/magiconair/properties/properties_test.go b/Godeps/_workspace/src/github.com/magiconair/properties/properties_test.go new file mode 100644 index 00000000..36ff2934 --- /dev/null +++ b/Godeps/_workspace/src/github.com/magiconair/properties/properties_test.go @@ -0,0 +1,846 @@ +// Copyright 2013-2014 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package properties + +import ( + "bytes" + "flag" + "fmt" + "math" + "os" + "strings" + "testing" + "time" + + . "gopkg.in/check.v1" +) + +func Test(t *testing.T) { TestingT(t) } + +type TestSuite struct { + prevHandler ErrorHandlerFunc +} + +var ( + _ = Suite(&TestSuite{}) + verbose = flag.Bool("verbose", false, "Verbose output") +) + +// -------------------------------------------------------------------- + +func (s *TestSuite) SetUpSuite(c *C) { + s.prevHandler = ErrorHandler + ErrorHandler = PanicHandler +} + +// -------------------------------------------------------------------- + +func (s *TestSuite) TearDownSuite(c *C) { + ErrorHandler = s.prevHandler +} + +// ---------------------------------------------------------------------------- + +// define test cases in the form of +// {"input", "key1", "value1", "key2", "value2", ...} +var complexTests = [][]string{ + // whitespace prefix + {" key=value", "key", "value"}, // SPACE prefix + {"\fkey=value", "key", "value"}, // FF prefix + {"\tkey=value", "key", "value"}, // TAB prefix + {" \f\tkey=value", "key", "value"}, // mix prefix + + // multiple keys + {"key1=value1\nkey2=value2\n", "key1", "value1", "key2", "value2"}, + {"key1=value1\rkey2=value2\r", "key1", "value1", "key2", "value2"}, + {"key1=value1\r\nkey2=value2\r\n", "key1", "value1", "key2", "value2"}, + + // blank lines + {"\nkey=value\n", "key", "value"}, + {"\rkey=value\r", "key", "value"}, + {"\r\nkey=value\r\n", "key", "value"}, + + // escaped chars in key + {"k\\ ey = value", "k ey", "value"}, + {"k\\:ey = value", "k:ey", "value"}, + {"k\\=ey = value", "k=ey", "value"}, + {"k\\fey = value", "k\fey", "value"}, + {"k\\ney = value", "k\ney", "value"}, + {"k\\rey = value", "k\rey", "value"}, + {"k\\tey = value", "k\tey", "value"}, + + // escaped chars in value + {"key = v\\ alue", "key", "v alue"}, + {"key = v\\:alue", "key", "v:alue"}, + {"key = v\\=alue", "key", "v=alue"}, + {"key = v\\falue", "key", "v\falue"}, + {"key = v\\nalue", "key", "v\nalue"}, + {"key = v\\ralue", "key", "v\ralue"}, + {"key = v\\talue", "key", "v\talue"}, + + // silently dropped escape character + {"k\\zey = value", "kzey", "value"}, + {"key = v\\zalue", "key", "vzalue"}, + + // unicode literals + {"key\\u2318 = value", "key⌘", "value"}, + {"k\\u2318ey = value", "k⌘ey", "value"}, + {"key = value\\u2318", "key", "value⌘"}, + {"key = valu\\u2318e", "key", "valu⌘e"}, + + // multiline values + {"key = valueA,\\\n valueB", "key", "valueA,valueB"}, // SPACE indent + {"key = valueA,\\\n\f\f\fvalueB", "key", "valueA,valueB"}, // FF indent + {"key = valueA,\\\n\t\t\tvalueB", "key", "valueA,valueB"}, // TAB indent + {"key = valueA,\\\n \f\tvalueB", "key", "valueA,valueB"}, // mix indent + + // comments + {"# this is a comment\n! and so is this\nkey1=value1\nkey#2=value#2\n\nkey!3=value!3\n# and another one\n! and the final one", "key1", "value1", "key#2", "value#2", "key!3", "value!3"}, + + // expansion tests + {"key=value\nkey2=${key}", "key", "value", "key2", "value"}, + {"key=value\nkey2=aa${key}", "key", "value", "key2", "aavalue"}, + {"key=value\nkey2=${key}bb", "key", "value", "key2", "valuebb"}, + {"key=value\nkey2=aa${key}bb", "key", "value", "key2", "aavaluebb"}, + {"key=value\nkey2=${key}\nkey3=${key2}", "key", "value", "key2", "value", "key3", "value"}, + {"key=${USER}", "key", os.Getenv("USER")}, + {"key=${USER}\nUSER=value", "key", "value", "USER", "value"}, +} + +// ---------------------------------------------------------------------------- + +var commentTests = []struct { + input, key, value string + comments []string +}{ + {"key=value", "key", "value", nil}, + {"#\nkey=value", "key", "value", []string{""}}, + {"#comment\nkey=value", "key", "value", []string{"comment"}}, + {"# comment\nkey=value", "key", "value", []string{"comment"}}, + {"# comment\nkey=value", "key", "value", []string{"comment"}}, + {"# comment\n\nkey=value", "key", "value", []string{"comment"}}, + {"# comment1\n# comment2\nkey=value", "key", "value", []string{"comment1", "comment2"}}, + {"# comment1\n\n# comment2\n\nkey=value", "key", "value", []string{"comment1", "comment2"}}, + {"!comment\nkey=value", "key", "value", []string{"comment"}}, + {"! comment\nkey=value", "key", "value", []string{"comment"}}, + {"! comment\nkey=value", "key", "value", []string{"comment"}}, + {"! comment\n\nkey=value", "key", "value", []string{"comment"}}, + {"! comment1\n! comment2\nkey=value", "key", "value", []string{"comment1", "comment2"}}, + {"! comment1\n\n! comment2\n\nkey=value", "key", "value", []string{"comment1", "comment2"}}, +} + +// ---------------------------------------------------------------------------- + +var errorTests = []struct { + input, msg string +}{ + // unicode literals + {"key\\u1 = value", "invalid unicode literal"}, + {"key\\u12 = value", "invalid unicode literal"}, + {"key\\u123 = value", "invalid unicode literal"}, + {"key\\u123g = value", "invalid unicode literal"}, + {"key\\u123", "invalid unicode literal"}, + + // circular references + {"key=${key}", "circular reference"}, + {"key1=${key2}\nkey2=${key1}", "circular reference"}, + + // malformed expressions + {"key=${ke", "malformed expression"}, + {"key=valu${ke", "malformed expression"}, +} + +// ---------------------------------------------------------------------------- + +var writeTests = []struct { + input, output, encoding string +}{ + // ISO-8859-1 tests + {"key = value", "key = value\n", "ISO-8859-1"}, + {"key = value \\\n continued", "key = value continued\n", "ISO-8859-1"}, + {"key⌘ = value", "key\\u2318 = value\n", "ISO-8859-1"}, + {"ke\\ \\:y = value", "ke\\ \\:y = value\n", "ISO-8859-1"}, + + // UTF-8 tests + {"key = value", "key = value\n", "UTF-8"}, + {"key = value \\\n continued", "key = value continued\n", "UTF-8"}, + {"key⌘ = value⌘", "key⌘ = value⌘\n", "UTF-8"}, + {"ke\\ \\:y = value", "ke\\ \\:y = value\n", "UTF-8"}, +} + +// ---------------------------------------------------------------------------- + +var writeCommentTests = []struct { + input, output, encoding string +}{ + // ISO-8859-1 tests + {"key = value", "key = value\n", "ISO-8859-1"}, + {"#\nkey = value", "key = value\n", "ISO-8859-1"}, + {"#\n#\n#\nkey = value", "key = value\n", "ISO-8859-1"}, + {"# comment\nkey = value", "# comment\nkey = value\n", "ISO-8859-1"}, + {"\n# comment\nkey = value", "# comment\nkey = value\n", "ISO-8859-1"}, + {"# comment\n\nkey = value", "# comment\nkey = value\n", "ISO-8859-1"}, + {"# comment1\n# comment2\nkey = value", "# comment1\n# comment2\nkey = value\n", "ISO-8859-1"}, + {"#comment1\nkey1 = value1\n#comment2\nkey2 = value2", "# comment1\nkey1 = value1\n\n# comment2\nkey2 = value2\n", "ISO-8859-1"}, + + // UTF-8 tests + {"key = value", "key = value\n", "UTF-8"}, + {"# comment⌘\nkey = value⌘", "# comment⌘\nkey = value⌘\n", "UTF-8"}, + {"\n# comment⌘\nkey = value⌘", "# comment⌘\nkey = value⌘\n", "UTF-8"}, + {"# comment⌘\n\nkey = value⌘", "# comment⌘\nkey = value⌘\n", "UTF-8"}, + {"# comment1⌘\n# comment2⌘\nkey = value⌘", "# comment1⌘\n# comment2⌘\nkey = value⌘\n", "UTF-8"}, + {"#comment1⌘\nkey1 = value1⌘\n#comment2⌘\nkey2 = value2⌘", "# comment1⌘\nkey1 = value1⌘\n\n# comment2⌘\nkey2 = value2⌘\n", "UTF-8"}, +} + +// ---------------------------------------------------------------------------- + +var boolTests = []struct { + input, key string + def, value bool +}{ + // valid values for TRUE + {"key = 1", "key", false, true}, + {"key = on", "key", false, true}, + {"key = On", "key", false, true}, + {"key = ON", "key", false, true}, + {"key = true", "key", false, true}, + {"key = True", "key", false, true}, + {"key = TRUE", "key", false, true}, + {"key = yes", "key", false, true}, + {"key = Yes", "key", false, true}, + {"key = YES", "key", false, true}, + + // valid values for FALSE (all other) + {"key = 0", "key", true, false}, + {"key = off", "key", true, false}, + {"key = false", "key", true, false}, + {"key = no", "key", true, false}, + + // non existent key + {"key = true", "key2", false, false}, +} + +// ---------------------------------------------------------------------------- + +var durationTests = []struct { + input, key string + def, value time.Duration +}{ + // valid values + {"key = 1", "key", 999, 1}, + {"key = 0", "key", 999, 0}, + {"key = -1", "key", 999, -1}, + {"key = 0123", "key", 999, 123}, + + // invalid values + {"key = 0xff", "key", 999, 999}, + {"key = 1.0", "key", 999, 999}, + {"key = a", "key", 999, 999}, + + // non existent key + {"key = 1", "key2", 999, 999}, +} + +// ---------------------------------------------------------------------------- + +var parsedDurationTests = []struct { + input, key string + def, value time.Duration +}{ + // valid values + {"key = -1ns", "key", 999, -1 * time.Nanosecond}, + {"key = 300ms", "key", 999, 300 * time.Millisecond}, + {"key = 5s", "key", 999, 5 * time.Second}, + {"key = 3h", "key", 999, 3 * time.Hour}, + {"key = 2h45m", "key", 999, 2*time.Hour + 45*time.Minute}, + + // invalid values + {"key = 0xff", "key", 999, 999}, + {"key = 1.0", "key", 999, 999}, + {"key = a", "key", 999, 999}, + {"key = 1", "key", 999, 999}, + {"key = 0", "key", 999, 0}, + + // non existent key + {"key = 1", "key2", 999, 999}, +} + +// ---------------------------------------------------------------------------- + +var floatTests = []struct { + input, key string + def, value float64 +}{ + // valid values + {"key = 1.0", "key", 999, 1.0}, + {"key = 0.0", "key", 999, 0.0}, + {"key = -1.0", "key", 999, -1.0}, + {"key = 1", "key", 999, 1}, + {"key = 0", "key", 999, 0}, + {"key = -1", "key", 999, -1}, + {"key = 0123", "key", 999, 123}, + + // invalid values + {"key = 0xff", "key", 999, 999}, + {"key = a", "key", 999, 999}, + + // non existent key + {"key = 1", "key2", 999, 999}, +} + +// ---------------------------------------------------------------------------- + +var int64Tests = []struct { + input, key string + def, value int64 +}{ + // valid values + {"key = 1", "key", 999, 1}, + {"key = 0", "key", 999, 0}, + {"key = -1", "key", 999, -1}, + {"key = 0123", "key", 999, 123}, + + // invalid values + {"key = 0xff", "key", 999, 999}, + {"key = 1.0", "key", 999, 999}, + {"key = a", "key", 999, 999}, + + // non existent key + {"key = 1", "key2", 999, 999}, +} + +// ---------------------------------------------------------------------------- + +var uint64Tests = []struct { + input, key string + def, value uint64 +}{ + // valid values + {"key = 1", "key", 999, 1}, + {"key = 0", "key", 999, 0}, + {"key = 0123", "key", 999, 123}, + + // invalid values + {"key = -1", "key", 999, 999}, + {"key = 0xff", "key", 999, 999}, + {"key = 1.0", "key", 999, 999}, + {"key = a", "key", 999, 999}, + + // non existent key + {"key = 1", "key2", 999, 999}, +} + +// ---------------------------------------------------------------------------- + +var stringTests = []struct { + input, key string + def, value string +}{ + // valid values + {"key = abc", "key", "def", "abc"}, + + // non existent key + {"key = abc", "key2", "def", "def"}, +} + +// ---------------------------------------------------------------------------- + +var keysTests = []struct { + input string + keys []string +}{ + {"", []string{}}, + {"key = abc", []string{"key"}}, + {"key = abc\nkey2=def", []string{"key", "key2"}}, + {"key2 = abc\nkey=def", []string{"key2", "key"}}, + {"key = abc\nkey=def", []string{"key"}}, +} + +// ---------------------------------------------------------------------------- + +var filterTests = []struct { + input string + pattern string + keys []string + err string +}{ + {"", "", []string{}, ""}, + {"", "abc", []string{}, ""}, + {"key=value", "", []string{"key"}, ""}, + {"key=value", "key=", []string{}, ""}, + {"key=value\nfoo=bar", "", []string{"foo", "key"}, ""}, + {"key=value\nfoo=bar", "f", []string{"foo"}, ""}, + {"key=value\nfoo=bar", "fo", []string{"foo"}, ""}, + {"key=value\nfoo=bar", "foo", []string{"foo"}, ""}, + {"key=value\nfoo=bar", "fooo", []string{}, ""}, + {"key=value\nkey2=value2\nfoo=bar", "ey", []string{"key", "key2"}, ""}, + {"key=value\nkey2=value2\nfoo=bar", "key", []string{"key", "key2"}, ""}, + {"key=value\nkey2=value2\nfoo=bar", "^key", []string{"key", "key2"}, ""}, + {"key=value\nkey2=value2\nfoo=bar", "^(key|foo)", []string{"foo", "key", "key2"}, ""}, + {"key=value\nkey2=value2\nfoo=bar", "[ abc", nil, "error parsing regexp.*"}, +} + +// ---------------------------------------------------------------------------- + +var filterPrefixTests = []struct { + input string + prefix string + keys []string +}{ + {"", "", []string{}}, + {"", "abc", []string{}}, + {"key=value", "", []string{"key"}}, + {"key=value", "key=", []string{}}, + {"key=value\nfoo=bar", "", []string{"foo", "key"}}, + {"key=value\nfoo=bar", "f", []string{"foo"}}, + {"key=value\nfoo=bar", "fo", []string{"foo"}}, + {"key=value\nfoo=bar", "foo", []string{"foo"}}, + {"key=value\nfoo=bar", "fooo", []string{}}, + {"key=value\nkey2=value2\nfoo=bar", "key", []string{"key", "key2"}}, +} + +// ---------------------------------------------------------------------------- + +var setTests = []struct { + input string + key, value string + prev string + ok bool + err string + keys []string +}{ + {"", "", "", "", false, "", []string{}}, + {"", "key", "value", "", false, "", []string{"key"}}, + {"key=value", "key2", "value2", "", false, "", []string{"key", "key2"}}, + {"key=value", "abc", "value3", "", false, "", []string{"key", "abc"}}, + {"key=value", "key", "value3", "value", true, "", []string{"key"}}, +} + +// ---------------------------------------------------------------------------- + +// TestBasic tests basic single key/value combinations with all possible +// whitespace, delimiter and newline permutations. +func (s *TestSuite) TestBasic(c *C) { + testWhitespaceAndDelimiterCombinations(c, "key", "") + testWhitespaceAndDelimiterCombinations(c, "key", "value") + testWhitespaceAndDelimiterCombinations(c, "key", "value ") +} + +func (s *TestSuite) TestComplex(c *C) { + for _, test := range complexTests { + testKeyValue(c, test[0], test[1:]...) + } +} + +func (s *TestSuite) TestErrors(c *C) { + for _, test := range errorTests { + _, err := Load([]byte(test.input), ISO_8859_1) + c.Assert(err, NotNil) + c.Assert(strings.Contains(err.Error(), test.msg), Equals, true, Commentf("Expected %q got %q", test.msg, err.Error())) + } +} + +func (s *TestSuite) TestMustGet(c *C) { + input := "key = value\nkey2 = ghi" + p, err := parse(input) + c.Assert(err, IsNil) + c.Assert(p.MustGet("key"), Equals, "value") + c.Assert(func() { p.MustGet("invalid") }, PanicMatches, "unknown property: invalid") +} + +func (s *TestSuite) TestGetBool(c *C) { + for _, test := range boolTests { + p, err := parse(test.input) + c.Assert(err, IsNil) + c.Assert(p.Len(), Equals, 1) + c.Assert(p.GetBool(test.key, test.def), Equals, test.value) + } +} + +func (s *TestSuite) TestMustGetBool(c *C) { + input := "key = true\nkey2 = ghi" + p, err := parse(input) + c.Assert(err, IsNil) + c.Assert(p.MustGetBool("key"), Equals, true) + c.Assert(func() { p.MustGetBool("invalid") }, PanicMatches, "unknown property: invalid") +} + +func (s *TestSuite) TestGetDuration(c *C) { + for _, test := range durationTests { + p, err := parse(test.input) + c.Assert(err, IsNil) + c.Assert(p.Len(), Equals, 1) + c.Assert(p.GetDuration(test.key, test.def), Equals, test.value) + } +} + +func (s *TestSuite) TestMustGetDuration(c *C) { + input := "key = 123\nkey2 = ghi" + p, err := parse(input) + c.Assert(err, IsNil) + c.Assert(p.MustGetDuration("key"), Equals, time.Duration(123)) + c.Assert(func() { p.MustGetDuration("key2") }, PanicMatches, "strconv.ParseInt: parsing.*") + c.Assert(func() { p.MustGetDuration("invalid") }, PanicMatches, "unknown property: invalid") +} + +func (s *TestSuite) TestGetParsedDuration(c *C) { + for _, test := range parsedDurationTests { + p, err := parse(test.input) + c.Assert(err, IsNil) + c.Assert(p.Len(), Equals, 1) + c.Assert(p.GetParsedDuration(test.key, test.def), Equals, test.value) + } +} + +func (s *TestSuite) TestMustGetParsedDuration(c *C) { + input := "key = 123ms\nkey2 = ghi" + p, err := parse(input) + c.Assert(err, IsNil) + c.Assert(p.MustGetParsedDuration("key"), Equals, 123*time.Millisecond) + c.Assert(func() { p.MustGetParsedDuration("key2") }, PanicMatches, "time: invalid duration ghi") + c.Assert(func() { p.MustGetParsedDuration("invalid") }, PanicMatches, "unknown property: invalid") +} + +func (s *TestSuite) TestGetFloat64(c *C) { + for _, test := range floatTests { + p, err := parse(test.input) + c.Assert(err, IsNil) + c.Assert(p.Len(), Equals, 1) + c.Assert(p.GetFloat64(test.key, test.def), Equals, test.value) + } +} + +func (s *TestSuite) TestMustGetFloat64(c *C) { + input := "key = 123\nkey2 = ghi" + p, err := parse(input) + c.Assert(err, IsNil) + c.Assert(p.MustGetFloat64("key"), Equals, float64(123)) + c.Assert(func() { p.MustGetFloat64("key2") }, PanicMatches, "strconv.ParseFloat: parsing.*") + c.Assert(func() { p.MustGetFloat64("invalid") }, PanicMatches, "unknown property: invalid") +} + +func (s *TestSuite) TestGetInt(c *C) { + for _, test := range int64Tests { + p, err := parse(test.input) + c.Assert(err, IsNil) + c.Assert(p.Len(), Equals, 1) + c.Assert(p.GetInt(test.key, int(test.def)), Equals, int(test.value)) + } +} + +func (s *TestSuite) TestMustGetInt(c *C) { + input := "key = 123\nkey2 = ghi" + p, err := parse(input) + c.Assert(err, IsNil) + c.Assert(p.MustGetInt("key"), Equals, int(123)) + c.Assert(func() { p.MustGetInt("key2") }, PanicMatches, "strconv.ParseInt: parsing.*") + c.Assert(func() { p.MustGetInt("invalid") }, PanicMatches, "unknown property: invalid") +} + +func (s *TestSuite) TestGetInt64(c *C) { + for _, test := range int64Tests { + p, err := parse(test.input) + c.Assert(err, IsNil) + c.Assert(p.Len(), Equals, 1) + c.Assert(p.GetInt64(test.key, test.def), Equals, test.value) + } +} + +func (s *TestSuite) TestMustGetInt64(c *C) { + input := "key = 123\nkey2 = ghi" + p, err := parse(input) + c.Assert(err, IsNil) + c.Assert(p.MustGetInt64("key"), Equals, int64(123)) + c.Assert(func() { p.MustGetInt64("key2") }, PanicMatches, "strconv.ParseInt: parsing.*") + c.Assert(func() { p.MustGetInt64("invalid") }, PanicMatches, "unknown property: invalid") +} + +func (s *TestSuite) TestGetUint(c *C) { + for _, test := range uint64Tests { + p, err := parse(test.input) + c.Assert(err, IsNil) + c.Assert(p.Len(), Equals, 1) + c.Assert(p.GetUint(test.key, uint(test.def)), Equals, uint(test.value)) + } +} + +func (s *TestSuite) TestMustGetUint(c *C) { + input := "key = 123\nkey2 = ghi" + p, err := parse(input) + c.Assert(err, IsNil) + c.Assert(p.MustGetUint("key"), Equals, uint(123)) + c.Assert(func() { p.MustGetUint64("key2") }, PanicMatches, "strconv.ParseUint: parsing.*") + c.Assert(func() { p.MustGetUint64("invalid") }, PanicMatches, "unknown property: invalid") +} + +func (s *TestSuite) TestGetUint64(c *C) { + for _, test := range uint64Tests { + p, err := parse(test.input) + c.Assert(err, IsNil) + c.Assert(p.Len(), Equals, 1) + c.Assert(p.GetUint64(test.key, test.def), Equals, test.value) + } +} + +func (s *TestSuite) TestMustGetUint64(c *C) { + input := "key = 123\nkey2 = ghi" + p, err := parse(input) + c.Assert(err, IsNil) + c.Assert(p.MustGetUint64("key"), Equals, uint64(123)) + c.Assert(func() { p.MustGetUint64("key2") }, PanicMatches, "strconv.ParseUint: parsing.*") + c.Assert(func() { p.MustGetUint64("invalid") }, PanicMatches, "unknown property: invalid") +} + +func (s *TestSuite) TestGetString(c *C) { + for _, test := range stringTests { + p, err := parse(test.input) + c.Assert(err, IsNil) + c.Assert(p.Len(), Equals, 1) + c.Assert(p.GetString(test.key, test.def), Equals, test.value) + } +} + +func (s *TestSuite) TestMustGetString(c *C) { + input := `key = value` + p, err := parse(input) + c.Assert(err, IsNil) + c.Assert(p.MustGetString("key"), Equals, "value") + c.Assert(func() { p.MustGetString("invalid") }, PanicMatches, "unknown property: invalid") +} + +func (s *TestSuite) TestComment(c *C) { + for _, test := range commentTests { + p, err := parse(test.input) + c.Assert(err, IsNil) + c.Assert(p.MustGetString(test.key), Equals, test.value) + c.Assert(p.GetComments(test.key), DeepEquals, test.comments) + if test.comments != nil { + c.Assert(p.GetComment(test.key), Equals, test.comments[len(test.comments)-1]) + } else { + c.Assert(p.GetComment(test.key), Equals, "") + } + + // test setting comments + if len(test.comments) > 0 { + // set single comment + p.ClearComments() + c.Assert(len(p.c), Equals, 0) + p.SetComment(test.key, test.comments[0]) + c.Assert(p.GetComment(test.key), Equals, test.comments[0]) + + // set multiple comments + p.ClearComments() + c.Assert(len(p.c), Equals, 0) + p.SetComments(test.key, test.comments) + c.Assert(p.GetComments(test.key), DeepEquals, test.comments) + + // clear comments for a key + p.SetComments(test.key, nil) + c.Assert(p.GetComment(test.key), Equals, "") + c.Assert(p.GetComments(test.key), IsNil) + } + } +} + +func (s *TestSuite) TestFilter(c *C) { + for _, test := range filterTests { + p, err := parse(test.input) + c.Assert(err, IsNil) + pp, err := p.Filter(test.pattern) + if err != nil { + c.Assert(err, ErrorMatches, test.err) + continue + } + c.Assert(pp, NotNil) + c.Assert(pp.Len(), Equals, len(test.keys)) + for _, key := range test.keys { + v1, ok1 := p.Get(key) + v2, ok2 := pp.Get(key) + c.Assert(ok1, Equals, true) + c.Assert(ok2, Equals, true) + c.Assert(v1, Equals, v2) + } + } +} + +func (s *TestSuite) TestFilterPrefix(c *C) { + for _, test := range filterPrefixTests { + p, err := parse(test.input) + c.Assert(err, IsNil) + pp := p.FilterPrefix(test.prefix) + c.Assert(pp, NotNil) + c.Assert(pp.Len(), Equals, len(test.keys)) + for _, key := range test.keys { + v1, ok1 := p.Get(key) + v2, ok2 := pp.Get(key) + c.Assert(ok1, Equals, true) + c.Assert(ok2, Equals, true) + c.Assert(v1, Equals, v2) + } + } +} + +func (s *TestSuite) TestKeys(c *C) { + for _, test := range keysTests { + p, err := parse(test.input) + c.Assert(err, IsNil) + c.Assert(p.Len(), Equals, len(test.keys)) + c.Assert(len(p.Keys()), Equals, len(test.keys)) + c.Assert(p.Keys(), DeepEquals, test.keys) + } +} + +func (s *TestSuite) TestSet(c *C) { + for _, test := range setTests { + p, err := parse(test.input) + c.Assert(err, IsNil) + prev, ok, err := p.Set(test.key, test.value) + if test.err != "" { + c.Assert(err, ErrorMatches, test.err) + continue + } + + c.Assert(err, IsNil) + c.Assert(ok, Equals, test.ok) + if ok { + c.Assert(prev, Equals, test.prev) + } + c.Assert(p.Keys(), DeepEquals, test.keys) + } +} + +func (s *TestSuite) TestMustSet(c *C) { + input := "key=${key}" + p, err := parse(input) + c.Assert(err, IsNil) + c.Assert(func() { p.MustSet("key", "${key}") }, PanicMatches, "circular reference .*") +} + +func (s *TestSuite) TestWrite(c *C) { + for _, test := range writeTests { + p, err := parse(test.input) + + buf := new(bytes.Buffer) + var n int + switch test.encoding { + case "UTF-8": + n, err = p.Write(buf, UTF8) + case "ISO-8859-1": + n, err = p.Write(buf, ISO_8859_1) + } + c.Assert(err, IsNil) + s := string(buf.Bytes()) + c.Assert(n, Equals, len(test.output), Commentf("input=%q expected=%q obtained=%q", test.input, test.output, s)) + c.Assert(s, Equals, test.output, Commentf("input=%q expected=%q obtained=%q", test.input, test.output, s)) + } +} + +func (s *TestSuite) TestWriteComment(c *C) { + for _, test := range writeCommentTests { + p, err := parse(test.input) + + buf := new(bytes.Buffer) + var n int + switch test.encoding { + case "UTF-8": + n, err = p.WriteComment(buf, "# ", UTF8) + case "ISO-8859-1": + n, err = p.WriteComment(buf, "# ", ISO_8859_1) + } + c.Assert(err, IsNil) + s := string(buf.Bytes()) + c.Assert(n, Equals, len(test.output), Commentf("input=%q expected=%q obtained=%q", test.input, test.output, s)) + c.Assert(s, Equals, test.output, Commentf("input=%q expected=%q obtained=%q", test.input, test.output, s)) + } +} + +func (s *TestSuite) TestCustomExpansionExpression(c *C) { + testKeyValuePrePostfix(c, "*[", "]*", "key=value\nkey2=*[key]*", "key", "value", "key2", "value") +} + +func (s *TestSuite) TestPanicOn32BitIntOverflow(c *C) { + is32Bit = true + var min, max int64 = math.MinInt32 - 1, math.MaxInt32 + 1 + input := fmt.Sprintf("min=%d\nmax=%d", min, max) + p, err := parse(input) + c.Assert(err, IsNil) + c.Assert(p.MustGetInt64("min"), Equals, min) + c.Assert(p.MustGetInt64("max"), Equals, max) + c.Assert(func() { p.MustGetInt("min") }, PanicMatches, ".* out of range") + c.Assert(func() { p.MustGetInt("max") }, PanicMatches, ".* out of range") +} + +func (s *TestSuite) TestPanicOn32BitUintOverflow(c *C) { + is32Bit = true + var max = math.MaxUint32 + 1 + input := fmt.Sprintf("max=%d", max) + p, err := parse(input) + c.Assert(err, IsNil) + c.Assert(p.MustGetUint64("max"), Equals, uint64(max)) + c.Assert(func() { p.MustGetUint("max") }, PanicMatches, ".* out of range") +} + +// ---------------------------------------------------------------------------- + +// tests all combinations of delimiters, leading and/or trailing whitespace and newlines. +func testWhitespaceAndDelimiterCombinations(c *C, key, value string) { + whitespace := []string{"", " ", "\f", "\t"} + delimiters := []string{"", " ", "=", ":"} + newlines := []string{"", "\r", "\n", "\r\n"} + for _, dl := range delimiters { + for _, ws1 := range whitespace { + for _, ws2 := range whitespace { + for _, nl := range newlines { + // skip the one case where there is nothing between a key and a value + if ws1 == "" && dl == "" && ws2 == "" && value != "" { + continue + } + + input := fmt.Sprintf("%s%s%s%s%s%s", key, ws1, dl, ws2, value, nl) + testKeyValue(c, input, key, value) + } + } + } + } +} + +// tests whether key/value pairs exist for a given input. +// keyvalues is expected to be an even number of strings of "key", "value", ... +func testKeyValue(c *C, input string, keyvalues ...string) { + testKeyValuePrePostfix(c, "${", "}", input, keyvalues...) +} + +// tests whether key/value pairs exist for a given input. +// keyvalues is expected to be an even number of strings of "key", "value", ... +func testKeyValuePrePostfix(c *C, prefix, postfix, input string, keyvalues ...string) { + printf("%q\n", input) + + p, err := Load([]byte(input), ISO_8859_1) + c.Assert(err, IsNil) + p.Prefix = prefix + p.Postfix = postfix + assertKeyValues(c, input, p, keyvalues...) +} + +// tests whether key/value pairs exist for a given input. +// keyvalues is expected to be an even number of strings of "key", "value", ... +func assertKeyValues(c *C, input string, p *Properties, keyvalues ...string) { + c.Assert(p, NotNil) + c.Assert(2*p.Len(), Equals, len(keyvalues), Commentf("Odd number of key/value pairs.")) + + for i := 0; i < len(keyvalues); i += 2 { + key, value := keyvalues[i], keyvalues[i+1] + v, ok := p.Get(key) + c.Assert(ok, Equals, true, Commentf("No key %q found (input=%q)", key, input)) + c.Assert(v, Equals, value, Commentf("Value %q does not match %q (input=%q)", v, value, input)) + } +} + +// prints to stderr if the -verbose flag was given. +func printf(format string, args ...interface{}) { + if *verbose { + fmt.Fprintf(os.Stderr, format, args...) + } +} diff --git a/Godeps/_workspace/src/github.com/magiconair/properties/rangecheck.go b/Godeps/_workspace/src/github.com/magiconair/properties/rangecheck.go new file mode 100644 index 00000000..6df4e6ca --- /dev/null +++ b/Godeps/_workspace/src/github.com/magiconair/properties/rangecheck.go @@ -0,0 +1,31 @@ +// Copyright 2013-2014 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package properties + +import ( + "fmt" + "math" +) + +// make this a var to overwrite it in a test +var is32Bit = ^uint(0) == math.MaxUint32 + +// intRangeCheck checks if the value fits into the int type and +// panics if it does not. +func intRangeCheck(key string, v int64) int { + if is32Bit && (v < math.MinInt32 || v > math.MaxInt32) { + panic(fmt.Sprintf("Value %d for key %s out of range", v, key)) + } + return int(v) +} + +// uintRangeCheck checks if the value fits into the uint type and +// panics if it does not. +func uintRangeCheck(key string, v uint64) uint { + if is32Bit && v > math.MaxUint32 { + panic(fmt.Sprintf("Value %d for key %s out of range", v, key)) + } + return uint(v) +} diff --git a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/.travis.yml b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/.travis.yml new file mode 100644 index 00000000..7f3fe9a9 --- /dev/null +++ b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/.travis.yml @@ -0,0 +1,7 @@ +language: go + +go: + - 1.4 + +script: + - go test diff --git a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/LICENSE b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/LICENSE new file mode 100644 index 00000000..f9c841a5 --- /dev/null +++ b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/README.md b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/README.md new file mode 100644 index 00000000..659d6885 --- /dev/null +++ b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/README.md @@ -0,0 +1,46 @@ +# mapstructure + +mapstructure is a Go library for decoding generic map values to structures +and vice versa, while providing helpful error handling. + +This library is most useful when decoding values from some data stream (JSON, +Gob, etc.) where you don't _quite_ know the structure of the underlying data +until you read a part of it. You can therefore read a `map[string]interface{}` +and use this library to decode it into the proper underlying native Go +structure. + +## Installation + +Standard `go get`: + +``` +$ go get github.com/mitchellh/mapstructure +``` + +## Usage & Example + +For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/mapstructure). + +The `Decode` function has examples associated with it there. + +## But Why?! + +Go offers fantastic standard libraries for decoding formats such as JSON. +The standard method is to have a struct pre-created, and populate that struct +from the bytes of the encoded format. This is great, but the problem is if +you have configuration or an encoding that changes slightly depending on +specific fields. For example, consider this JSON: + +```json +{ + "type": "person", + "name": "Mitchell" +} +``` + +Perhaps we can't populate a specific structure without first reading +the "type" field from the JSON. We could always do two passes over the +decoding of the JSON (reading the "type" first, and the rest later). +However, it is much simpler to just decode this into a `map[string]interface{}` +structure, read the "type" key, then use something like this library +to decode it into the proper structure. diff --git a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/decode_hooks.go b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/decode_hooks.go new file mode 100644 index 00000000..aa91f76c --- /dev/null +++ b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/decode_hooks.go @@ -0,0 +1,151 @@ +package mapstructure + +import ( + "errors" + "reflect" + "strconv" + "strings" + "time" +) + +// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns +// it into the proper DecodeHookFunc type, such as DecodeHookFuncType. +func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { + // Create variables here so we can reference them with the reflect pkg + var f1 DecodeHookFuncType + var f2 DecodeHookFuncKind + + // Fill in the variables into this interface and the rest is done + // automatically using the reflect package. + potential := []interface{}{f1, f2} + + v := reflect.ValueOf(h) + vt := v.Type() + for _, raw := range potential { + pt := reflect.ValueOf(raw).Type() + if vt.ConvertibleTo(pt) { + return v.Convert(pt).Interface() + } + } + + return nil +} + +// DecodeHookExec executes the given decode hook. This should be used +// since it'll naturally degrade to the older backwards compatible DecodeHookFunc +// that took reflect.Kind instead of reflect.Type. +func DecodeHookExec( + raw DecodeHookFunc, + from reflect.Type, to reflect.Type, + data interface{}) (interface{}, error) { + // Build our arguments that reflect expects + argVals := make([]reflect.Value, 3) + argVals[0] = reflect.ValueOf(from) + argVals[1] = reflect.ValueOf(to) + argVals[2] = reflect.ValueOf(data) + + switch f := typedDecodeHook(raw).(type) { + case DecodeHookFuncType: + return f(from, to, data) + case DecodeHookFuncKind: + return f(from.Kind(), to.Kind(), data) + default: + return nil, errors.New("invalid decode hook signature") + } +} + +// ComposeDecodeHookFunc creates a single DecodeHookFunc that +// automatically composes multiple DecodeHookFuncs. +// +// The composed funcs are called in order, with the result of the +// previous transformation. +func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + var err error + for _, f1 := range fs { + data, err = DecodeHookExec(f1, f, t, data) + if err != nil { + return nil, err + } + + // Modify the from kind to be correct with the new data + f = reflect.ValueOf(data).Type() + } + + return data, nil + } +} + +// StringToSliceHookFunc returns a DecodeHookFunc that converts +// string to []string by splitting on the given sep. +func StringToSliceHookFunc(sep string) DecodeHookFunc { + return func( + f reflect.Kind, + t reflect.Kind, + data interface{}) (interface{}, error) { + if f != reflect.String || t != reflect.Slice { + return data, nil + } + + raw := data.(string) + if raw == "" { + return []string{}, nil + } + + return strings.Split(raw, sep), nil + } +} + +// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts +// strings to time.Duration. +func StringToTimeDurationHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Duration(5)) { + return data, nil + } + + // Convert it by parsing + return time.ParseDuration(data.(string)) + } +} + +func WeaklyTypedHook( + f reflect.Kind, + t reflect.Kind, + data interface{}) (interface{}, error) { + dataVal := reflect.ValueOf(data) + switch t { + case reflect.String: + switch f { + case reflect.Bool: + if dataVal.Bool() { + return "1", nil + } else { + return "0", nil + } + case reflect.Float32: + return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil + case reflect.Int: + return strconv.FormatInt(dataVal.Int(), 10), nil + case reflect.Slice: + dataType := dataVal.Type() + elemKind := dataType.Elem().Kind() + if elemKind == reflect.Uint8 { + return string(dataVal.Interface().([]uint8)), nil + } + case reflect.Uint: + return strconv.FormatUint(dataVal.Uint(), 10), nil + } + } + + return data, nil +} diff --git a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/decode_hooks_test.go b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/decode_hooks_test.go new file mode 100644 index 00000000..53289afc --- /dev/null +++ b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/decode_hooks_test.go @@ -0,0 +1,229 @@ +package mapstructure + +import ( + "errors" + "reflect" + "testing" + "time" +) + +func TestComposeDecodeHookFunc(t *testing.T) { + f1 := func( + f reflect.Kind, + t reflect.Kind, + data interface{}) (interface{}, error) { + return data.(string) + "foo", nil + } + + f2 := func( + f reflect.Kind, + t reflect.Kind, + data interface{}) (interface{}, error) { + return data.(string) + "bar", nil + } + + f := ComposeDecodeHookFunc(f1, f2) + + result, err := DecodeHookExec( + f, reflect.TypeOf(""), reflect.TypeOf([]byte("")), "") + if err != nil { + t.Fatalf("bad: %s", err) + } + if result.(string) != "foobar" { + t.Fatalf("bad: %#v", result) + } +} + +func TestComposeDecodeHookFunc_err(t *testing.T) { + f1 := func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) { + return nil, errors.New("foo") + } + + f2 := func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) { + panic("NOPE") + } + + f := ComposeDecodeHookFunc(f1, f2) + + _, err := DecodeHookExec( + f, reflect.TypeOf(""), reflect.TypeOf([]byte("")), 42) + if err.Error() != "foo" { + t.Fatalf("bad: %s", err) + } +} + +func TestComposeDecodeHookFunc_kinds(t *testing.T) { + var f2From reflect.Kind + + f1 := func( + f reflect.Kind, + t reflect.Kind, + data interface{}) (interface{}, error) { + return int(42), nil + } + + f2 := func( + f reflect.Kind, + t reflect.Kind, + data interface{}) (interface{}, error) { + f2From = f + return data, nil + } + + f := ComposeDecodeHookFunc(f1, f2) + + _, err := DecodeHookExec( + f, reflect.TypeOf(""), reflect.TypeOf([]byte("")), "") + if err != nil { + t.Fatalf("bad: %s", err) + } + if f2From != reflect.Int { + t.Fatalf("bad: %#v", f2From) + } +} + +func TestStringToSliceHookFunc(t *testing.T) { + f := StringToSliceHookFunc(",") + + strType := reflect.TypeOf("") + sliceType := reflect.TypeOf([]byte("")) + cases := []struct { + f, t reflect.Type + data interface{} + result interface{} + err bool + }{ + {sliceType, sliceType, 42, 42, false}, + {strType, strType, 42, 42, false}, + { + strType, + sliceType, + "foo,bar,baz", + []string{"foo", "bar", "baz"}, + false, + }, + { + strType, + sliceType, + "", + []string{}, + false, + }, + } + + for i, tc := range cases { + actual, err := DecodeHookExec(f, tc.f, tc.t, tc.data) + if tc.err != (err != nil) { + t.Fatalf("case %d: expected err %#v", i, tc.err) + } + if !reflect.DeepEqual(actual, tc.result) { + t.Fatalf( + "case %d: expected %#v, got %#v", + i, tc.result, actual) + } + } +} + +func TestStringToTimeDurationHookFunc(t *testing.T) { + f := StringToTimeDurationHookFunc() + + strType := reflect.TypeOf("") + timeType := reflect.TypeOf(time.Duration(5)) + cases := []struct { + f, t reflect.Type + data interface{} + result interface{} + err bool + }{ + {strType, timeType, "5s", 5 * time.Second, false}, + {strType, timeType, "5", time.Duration(0), true}, + {strType, strType, "5", "5", false}, + } + + for i, tc := range cases { + actual, err := DecodeHookExec(f, tc.f, tc.t, tc.data) + if tc.err != (err != nil) { + t.Fatalf("case %d: expected err %#v", i, tc.err) + } + if !reflect.DeepEqual(actual, tc.result) { + t.Fatalf( + "case %d: expected %#v, got %#v", + i, tc.result, actual) + } + } +} + +func TestWeaklyTypedHook(t *testing.T) { + var f DecodeHookFunc = WeaklyTypedHook + + boolType := reflect.TypeOf(true) + strType := reflect.TypeOf("") + sliceType := reflect.TypeOf([]byte("")) + cases := []struct { + f, t reflect.Type + data interface{} + result interface{} + err bool + }{ + // TO STRING + { + boolType, + strType, + false, + "0", + false, + }, + + { + boolType, + strType, + true, + "1", + false, + }, + + { + reflect.TypeOf(float32(1)), + strType, + float32(7), + "7", + false, + }, + + { + reflect.TypeOf(int(1)), + strType, + int(7), + "7", + false, + }, + + { + sliceType, + strType, + []uint8("foo"), + "foo", + false, + }, + + { + reflect.TypeOf(uint(1)), + strType, + uint(7), + "7", + false, + }, + } + + for i, tc := range cases { + actual, err := DecodeHookExec(f, tc.f, tc.t, tc.data) + if tc.err != (err != nil) { + t.Fatalf("case %d: expected err %#v", i, tc.err) + } + if !reflect.DeepEqual(actual, tc.result) { + t.Fatalf( + "case %d: expected %#v, got %#v", + i, tc.result, actual) + } + } +} diff --git a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/error.go b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/error.go new file mode 100644 index 00000000..f97c4164 --- /dev/null +++ b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/error.go @@ -0,0 +1,34 @@ +package mapstructure + +import ( + "fmt" + "sort" + "strings" +) + +// Error implements the error interface and can represents multiple +// errors that occur in the course of a single decode. +type Error struct { + Errors []string +} + +func (e *Error) Error() string { + points := make([]string, len(e.Errors)) + for i, err := range e.Errors { + points[i] = fmt.Sprintf("* %s", err) + } + + sort.Strings(points) + return fmt.Sprintf( + "%d error(s) decoding:\n\n%s", + len(e.Errors), strings.Join(points, "\n")) +} + +func appendErrors(errors []string, err error) []string { + switch e := err.(type) { + case *Error: + return append(errors, e.Errors...) + default: + return append(errors, e.Error()) + } +} diff --git a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure.go b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure.go new file mode 100644 index 00000000..c5e33bea --- /dev/null +++ b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure.go @@ -0,0 +1,735 @@ +// The mapstructure package exposes functionality to convert an +// abitrary map[string]interface{} into a native Go structure. +// +// The Go structure can be arbitrarily complex, containing slices, +// other structs, etc. and the decoder will properly decode nested +// maps and so on into the proper structures in the native Go struct. +// See the examples to see what the decoder is capable of. +package mapstructure + +import ( + "errors" + "fmt" + "reflect" + "sort" + "strconv" + "strings" +) + +// DecodeHookFunc is the callback function that can be used for +// data transformations. See "DecodeHook" in the DecoderConfig +// struct. +// +// The type should be DecodeHookFuncType or DecodeHookFuncKind. +// Either is accepted. Types are a superset of Kinds (Types can return +// Kinds) and are generally a richer thing to use, but Kinds are simpler +// if you only need those. +// +// The reason DecodeHookFunc is multi-typed is for backwards compatibility: +// we started with Kinds and then realized Types were the better solution, +// but have a promise to not break backwards compat so we now support +// both. +type DecodeHookFunc interface{} + +type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) +type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) + +// DecoderConfig is the configuration that is used to create a new decoder +// and allows customization of various aspects of decoding. +type DecoderConfig struct { + // DecodeHook, if set, will be called before any decoding and any + // type conversion (if WeaklyTypedInput is on). This lets you modify + // the values before they're set down onto the resulting struct. + // + // If an error is returned, the entire decode will fail with that + // error. + DecodeHook DecodeHookFunc + + // If ErrorUnused is true, then it is an error for there to exist + // keys in the original map that were unused in the decoding process + // (extra keys). + ErrorUnused bool + + // If WeaklyTypedInput is true, the decoder will make the following + // "weak" conversions: + // + // - bools to string (true = "1", false = "0") + // - numbers to string (base 10) + // - bools to int/uint (true = 1, false = 0) + // - strings to int/uint (base implied by prefix) + // - int to bool (true if value != 0) + // - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F, + // FALSE, false, False. Anything else is an error) + // - empty array = empty map and vice versa + // - negative numbers to overflowed uint values (base 10) + // + WeaklyTypedInput bool + + // Metadata is the struct that will contain extra metadata about + // the decoding. If this is nil, then no metadata will be tracked. + Metadata *Metadata + + // Result is a pointer to the struct that will contain the decoded + // value. + Result interface{} + + // The tag name that mapstructure reads for field names. This + // defaults to "mapstructure" + TagName string +} + +// A Decoder takes a raw interface value and turns it into structured +// data, keeping track of rich error information along the way in case +// anything goes wrong. Unlike the basic top-level Decode method, you can +// more finely control how the Decoder behaves using the DecoderConfig +// structure. The top-level Decode method is just a convenience that sets +// up the most basic Decoder. +type Decoder struct { + config *DecoderConfig +} + +// Metadata contains information about decoding a structure that +// is tedious or difficult to get otherwise. +type Metadata struct { + // Keys are the keys of the structure which were successfully decoded + Keys []string + + // Unused is a slice of keys that were found in the raw value but + // weren't decoded since there was no matching field in the result interface + Unused []string +} + +// Decode takes a map and uses reflection to convert it into the +// given Go native structure. val must be a pointer to a struct. +func Decode(m interface{}, rawVal interface{}) error { + config := &DecoderConfig{ + Metadata: nil, + Result: rawVal, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(m) +} + +// WeakDecode is the same as Decode but is shorthand to enable +// WeaklyTypedInput. See DecoderConfig for more info. +func WeakDecode(input, output interface{}) error { + config := &DecoderConfig{ + Metadata: nil, + Result: output, + WeaklyTypedInput: true, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// NewDecoder returns a new decoder for the given configuration. Once +// a decoder has been returned, the same configuration must not be used +// again. +func NewDecoder(config *DecoderConfig) (*Decoder, error) { + val := reflect.ValueOf(config.Result) + if val.Kind() != reflect.Ptr { + return nil, errors.New("result must be a pointer") + } + + val = val.Elem() + if !val.CanAddr() { + return nil, errors.New("result must be addressable (a pointer)") + } + + if config.Metadata != nil { + if config.Metadata.Keys == nil { + config.Metadata.Keys = make([]string, 0) + } + + if config.Metadata.Unused == nil { + config.Metadata.Unused = make([]string, 0) + } + } + + if config.TagName == "" { + config.TagName = "mapstructure" + } + + result := &Decoder{ + config: config, + } + + return result, nil +} + +// Decode decodes the given raw interface to the target pointer specified +// by the configuration. +func (d *Decoder) Decode(raw interface{}) error { + return d.decode("", raw, reflect.ValueOf(d.config.Result).Elem()) +} + +// Decodes an unknown data type into a specific reflection value. +func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error { + if data == nil { + // If the data is nil, then we don't set anything. + return nil + } + + dataVal := reflect.ValueOf(data) + if !dataVal.IsValid() { + // If the data value is invalid, then we just set the value + // to be the zero value. + val.Set(reflect.Zero(val.Type())) + return nil + } + + if d.config.DecodeHook != nil { + // We have a DecodeHook, so let's pre-process the data. + var err error + data, err = DecodeHookExec( + d.config.DecodeHook, + dataVal.Type(), val.Type(), data) + if err != nil { + return err + } + } + + var err error + dataKind := getKind(val) + switch dataKind { + case reflect.Bool: + err = d.decodeBool(name, data, val) + case reflect.Interface: + err = d.decodeBasic(name, data, val) + case reflect.String: + err = d.decodeString(name, data, val) + case reflect.Int: + err = d.decodeInt(name, data, val) + case reflect.Uint: + err = d.decodeUint(name, data, val) + case reflect.Float32: + err = d.decodeFloat(name, data, val) + case reflect.Struct: + err = d.decodeStruct(name, data, val) + case reflect.Map: + err = d.decodeMap(name, data, val) + case reflect.Ptr: + err = d.decodePtr(name, data, val) + case reflect.Slice: + err = d.decodeSlice(name, data, val) + default: + // If we reached this point then we weren't able to decode it + return fmt.Errorf("%s: unsupported type: %s", name, dataKind) + } + + // If we reached here, then we successfully decoded SOMETHING, so + // mark the key as used if we're tracking metadata. + if d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + + return err +} + +// This decodes a basic type (bool, int, string, etc.) and sets the +// value to "data" of that type. +func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.ValueOf(data) + dataValType := dataVal.Type() + if !dataValType.AssignableTo(val.Type()) { + return fmt.Errorf( + "'%s' expected type '%s', got '%s'", + name, val.Type(), dataValType) + } + + val.Set(dataVal) + return nil +} + +func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.ValueOf(data) + dataKind := getKind(dataVal) + + converted := true + switch { + case dataKind == reflect.String: + val.SetString(dataVal.String()) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetString("1") + } else { + val.SetString("0") + } + case dataKind == reflect.Int && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatInt(dataVal.Int(), 10)) + case dataKind == reflect.Uint && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatUint(dataVal.Uint(), 10)) + case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64)) + case dataKind == reflect.Slice && d.config.WeaklyTypedInput: + dataType := dataVal.Type() + elemKind := dataType.Elem().Kind() + switch { + case elemKind == reflect.Uint8: + val.SetString(string(dataVal.Interface().([]uint8))) + default: + converted = false + } + default: + converted = false + } + + if !converted { + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.ValueOf(data) + dataKind := getKind(dataVal) + + switch { + case dataKind == reflect.Int: + val.SetInt(dataVal.Int()) + case dataKind == reflect.Uint: + val.SetInt(int64(dataVal.Uint())) + case dataKind == reflect.Float32: + val.SetInt(int64(dataVal.Float())) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetInt(1) + } else { + val.SetInt(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + i, err := strconv.ParseInt(dataVal.String(), 0, val.Type().Bits()) + if err == nil { + val.SetInt(i) + } else { + return fmt.Errorf("cannot parse '%s' as int: %s", name, err) + } + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.ValueOf(data) + dataKind := getKind(dataVal) + + switch { + case dataKind == reflect.Int: + i := dataVal.Int() + if i < 0 && !d.config.WeaklyTypedInput { + return fmt.Errorf("cannot parse '%s', %d overflows uint", + name, i) + } + val.SetUint(uint64(i)) + case dataKind == reflect.Uint: + val.SetUint(dataVal.Uint()) + case dataKind == reflect.Float32: + f := dataVal.Float() + if f < 0 && !d.config.WeaklyTypedInput { + return fmt.Errorf("cannot parse '%s', %f overflows uint", + name, f) + } + val.SetUint(uint64(f)) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetUint(1) + } else { + val.SetUint(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + i, err := strconv.ParseUint(dataVal.String(), 0, val.Type().Bits()) + if err == nil { + val.SetUint(i) + } else { + return fmt.Errorf("cannot parse '%s' as uint: %s", name, err) + } + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.ValueOf(data) + dataKind := getKind(dataVal) + + switch { + case dataKind == reflect.Bool: + val.SetBool(dataVal.Bool()) + case dataKind == reflect.Int && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Int() != 0) + case dataKind == reflect.Uint && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Uint() != 0) + case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Float() != 0) + case dataKind == reflect.String && d.config.WeaklyTypedInput: + b, err := strconv.ParseBool(dataVal.String()) + if err == nil { + val.SetBool(b) + } else if dataVal.String() == "" { + val.SetBool(false) + } else { + return fmt.Errorf("cannot parse '%s' as bool: %s", name, err) + } + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.ValueOf(data) + dataKind := getKind(dataVal) + + switch { + case dataKind == reflect.Int: + val.SetFloat(float64(dataVal.Int())) + case dataKind == reflect.Uint: + val.SetFloat(float64(dataVal.Uint())) + case dataKind == reflect.Float32: + val.SetFloat(float64(dataVal.Float())) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetFloat(1) + } else { + val.SetFloat(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + f, err := strconv.ParseFloat(dataVal.String(), val.Type().Bits()) + if err == nil { + val.SetFloat(f) + } else { + return fmt.Errorf("cannot parse '%s' as float: %s", name, err) + } + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { + valType := val.Type() + valKeyType := valType.Key() + valElemType := valType.Elem() + + // Make a new map to hold our result + mapType := reflect.MapOf(valKeyType, valElemType) + valMap := reflect.MakeMap(mapType) + + // Check input type + dataVal := reflect.Indirect(reflect.ValueOf(data)) + if dataVal.Kind() != reflect.Map { + // Accept empty array/slice instead of an empty map in weakly typed mode + if d.config.WeaklyTypedInput && + (dataVal.Kind() == reflect.Slice || dataVal.Kind() == reflect.Array) && + dataVal.Len() == 0 { + val.Set(valMap) + return nil + } else { + return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + } + } + + // Accumulate errors + errors := make([]string, 0) + + for _, k := range dataVal.MapKeys() { + fieldName := fmt.Sprintf("%s[%s]", name, k) + + // First decode the key into the proper type + currentKey := reflect.Indirect(reflect.New(valKeyType)) + if err := d.decode(fieldName, k.Interface(), currentKey); err != nil { + errors = appendErrors(errors, err) + continue + } + + // Next decode the data into the proper type + v := dataVal.MapIndex(k).Interface() + currentVal := reflect.Indirect(reflect.New(valElemType)) + if err := d.decode(fieldName, v, currentVal); err != nil { + errors = appendErrors(errors, err) + continue + } + + valMap.SetMapIndex(currentKey, currentVal) + } + + // Set the built up map to the value + val.Set(valMap) + + // If we had errors, return those + if len(errors) > 0 { + return &Error{errors} + } + + return nil +} + +func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) error { + // Create an element of the concrete (non pointer) type and decode + // into that. Then set the value of the pointer to this type. + valType := val.Type() + valElemType := valType.Elem() + realVal := reflect.New(valElemType) + if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil { + return err + } + + val.Set(realVal) + return nil +} + +func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataValKind := dataVal.Kind() + valType := val.Type() + valElemType := valType.Elem() + sliceType := reflect.SliceOf(valElemType) + + // Check input type + if dataValKind != reflect.Array && dataValKind != reflect.Slice { + // Accept empty map instead of array/slice in weakly typed mode + if d.config.WeaklyTypedInput && dataVal.Kind() == reflect.Map && dataVal.Len() == 0 { + val.Set(reflect.MakeSlice(sliceType, 0, 0)) + return nil + } else { + return fmt.Errorf( + "'%s': source data must be an array or slice, got %s", name, dataValKind) + } + } + + // Make a new slice to hold our result, same size as the original data. + valSlice := reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len()) + + // Accumulate any errors + errors := make([]string, 0) + + for i := 0; i < dataVal.Len(); i++ { + currentData := dataVal.Index(i).Interface() + currentField := valSlice.Index(i) + + fieldName := fmt.Sprintf("%s[%d]", name, i) + if err := d.decode(fieldName, currentData, currentField); err != nil { + errors = appendErrors(errors, err) + } + } + + // Finally, set the value to the slice we built up + val.Set(valSlice) + + // If there were errors, we return those + if len(errors) > 0 { + return &Error{errors} + } + + return nil +} + +func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + + // If the type of the value to write to and the data match directly, + // then we just set it directly instead of recursing into the structure. + if dataVal.Type() == val.Type() { + val.Set(dataVal) + return nil + } + + dataValKind := dataVal.Kind() + if dataValKind != reflect.Map { + return fmt.Errorf("'%s' expected a map, got '%s'", name, dataValKind) + } + + dataValType := dataVal.Type() + if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { + return fmt.Errorf( + "'%s' needs a map with string keys, has '%s' keys", + name, dataValType.Key().Kind()) + } + + dataValKeys := make(map[reflect.Value]struct{}) + dataValKeysUnused := make(map[interface{}]struct{}) + for _, dataValKey := range dataVal.MapKeys() { + dataValKeys[dataValKey] = struct{}{} + dataValKeysUnused[dataValKey.Interface()] = struct{}{} + } + + errors := make([]string, 0) + + // This slice will keep track of all the structs we'll be decoding. + // There can be more than one struct if there are embedded structs + // that are squashed. + structs := make([]reflect.Value, 1, 5) + structs[0] = val + + // Compile the list of all the fields that we're going to be decoding + // from all the structs. + fields := make(map[*reflect.StructField]reflect.Value) + for len(structs) > 0 { + structVal := structs[0] + structs = structs[1:] + + structType := structVal.Type() + for i := 0; i < structType.NumField(); i++ { + fieldType := structType.Field(i) + + if fieldType.Anonymous { + fieldKind := fieldType.Type.Kind() + if fieldKind != reflect.Struct { + errors = appendErrors(errors, + fmt.Errorf("%s: unsupported type: %s", fieldType.Name, fieldKind)) + continue + } + + // We have an embedded field. We "squash" the fields down + // if specified in the tag. + squash := false + tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",") + for _, tag := range tagParts[1:] { + if tag == "squash" { + squash = true + break + } + } + + if squash { + structs = append(structs, val.FieldByName(fieldType.Name)) + continue + } + } + + // Normal struct field, store it away + fields[&fieldType] = structVal.Field(i) + } + } + + for fieldType, field := range fields { + fieldName := fieldType.Name + + tagValue := fieldType.Tag.Get(d.config.TagName) + tagValue = strings.SplitN(tagValue, ",", 2)[0] + if tagValue != "" { + fieldName = tagValue + } + + rawMapKey := reflect.ValueOf(fieldName) + rawMapVal := dataVal.MapIndex(rawMapKey) + if !rawMapVal.IsValid() { + // Do a slower search by iterating over each key and + // doing case-insensitive search. + for dataValKey, _ := range dataValKeys { + mK, ok := dataValKey.Interface().(string) + if !ok { + // Not a string key + continue + } + + if strings.EqualFold(mK, fieldName) { + rawMapKey = dataValKey + rawMapVal = dataVal.MapIndex(dataValKey) + break + } + } + + if !rawMapVal.IsValid() { + // There was no matching key in the map for the value in + // the struct. Just ignore. + continue + } + } + + // Delete the key we're using from the unused map so we stop tracking + delete(dataValKeysUnused, rawMapKey.Interface()) + + if !field.IsValid() { + // This should never happen + panic("field is not valid") + } + + // If we can't set the field, then it is unexported or something, + // and we just continue onwards. + if !field.CanSet() { + continue + } + + // If the name is empty string, then we're at the root, and we + // don't dot-join the fields. + if name != "" { + fieldName = fmt.Sprintf("%s.%s", name, fieldName) + } + + if err := d.decode(fieldName, rawMapVal.Interface(), field); err != nil { + errors = appendErrors(errors, err) + } + } + + if d.config.ErrorUnused && len(dataValKeysUnused) > 0 { + keys := make([]string, 0, len(dataValKeysUnused)) + for rawKey, _ := range dataValKeysUnused { + keys = append(keys, rawKey.(string)) + } + sort.Strings(keys) + + err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", ")) + errors = appendErrors(errors, err) + } + + if len(errors) > 0 { + return &Error{errors} + } + + // Add the unused keys to the list of unused keys if we're tracking metadata + if d.config.Metadata != nil { + for rawKey, _ := range dataValKeysUnused { + key := rawKey.(string) + if name != "" { + key = fmt.Sprintf("%s.%s", name, key) + } + + d.config.Metadata.Unused = append(d.config.Metadata.Unused, key) + } + } + + return nil +} + +func getKind(val reflect.Value) reflect.Kind { + kind := val.Kind() + + switch { + case kind >= reflect.Int && kind <= reflect.Int64: + return reflect.Int + case kind >= reflect.Uint && kind <= reflect.Uint64: + return reflect.Uint + case kind >= reflect.Float32 && kind <= reflect.Float64: + return reflect.Float32 + default: + return kind + } +} diff --git a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_benchmark_test.go b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_benchmark_test.go new file mode 100644 index 00000000..b50ac36e --- /dev/null +++ b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_benchmark_test.go @@ -0,0 +1,243 @@ +package mapstructure + +import ( + "testing" +) + +func Benchmark_Decode(b *testing.B) { + type Person struct { + Name string + Age int + Emails []string + Extra map[string]string + } + + input := map[string]interface{}{ + "name": "Mitchell", + "age": 91, + "emails": []string{"one", "two", "three"}, + "extra": map[string]string{ + "twitter": "mitchellh", + }, + } + + var result Person + for i := 0; i < b.N; i++ { + Decode(input, &result) + } +} + +func Benchmark_DecodeBasic(b *testing.B) { + input := map[string]interface{}{ + "vstring": "foo", + "vint": 42, + "Vuint": 42, + "vbool": true, + "Vfloat": 42.42, + "vsilent": true, + "vdata": 42, + } + + var result Basic + for i := 0; i < b.N; i++ { + Decode(input, &result) + } +} + +func Benchmark_DecodeEmbedded(b *testing.B) { + input := map[string]interface{}{ + "vstring": "foo", + "Basic": map[string]interface{}{ + "vstring": "innerfoo", + }, + "vunique": "bar", + } + + var result Embedded + for i := 0; i < b.N; i++ { + Decode(input, &result) + } +} + +func Benchmark_DecodeTypeConversion(b *testing.B) { + input := map[string]interface{}{ + "IntToFloat": 42, + "IntToUint": 42, + "IntToBool": 1, + "IntToString": 42, + "UintToInt": 42, + "UintToFloat": 42, + "UintToBool": 42, + "UintToString": 42, + "BoolToInt": true, + "BoolToUint": true, + "BoolToFloat": true, + "BoolToString": true, + "FloatToInt": 42.42, + "FloatToUint": 42.42, + "FloatToBool": 42.42, + "FloatToString": 42.42, + "StringToInt": "42", + "StringToUint": "42", + "StringToBool": "1", + "StringToFloat": "42.42", + "SliceToMap": []interface{}{}, + "MapToSlice": map[string]interface{}{}, + } + + var resultStrict TypeConversionResult + for i := 0; i < b.N; i++ { + Decode(input, &resultStrict) + } +} + +func Benchmark_DecodeMap(b *testing.B) { + input := map[string]interface{}{ + "vfoo": "foo", + "vother": map[interface{}]interface{}{ + "foo": "foo", + "bar": "bar", + }, + } + + var result Map + for i := 0; i < b.N; i++ { + Decode(input, &result) + } +} + +func Benchmark_DecodeMapOfStruct(b *testing.B) { + input := map[string]interface{}{ + "value": map[string]interface{}{ + "foo": map[string]string{"vstring": "one"}, + "bar": map[string]string{"vstring": "two"}, + }, + } + + var result MapOfStruct + for i := 0; i < b.N; i++ { + Decode(input, &result) + } +} + +func Benchmark_DecodeSlice(b *testing.B) { + input := map[string]interface{}{ + "vfoo": "foo", + "vbar": []string{"foo", "bar", "baz"}, + } + + var result Slice + for i := 0; i < b.N; i++ { + Decode(input, &result) + } +} + +func Benchmark_DecodeSliceOfStruct(b *testing.B) { + input := map[string]interface{}{ + "value": []map[string]interface{}{ + {"vstring": "one"}, + {"vstring": "two"}, + }, + } + + var result SliceOfStruct + for i := 0; i < b.N; i++ { + Decode(input, &result) + } +} + +func Benchmark_DecodeWeaklyTypedInput(b *testing.B) { + type Person struct { + Name string + Age int + Emails []string + } + + // This input can come from anywhere, but typically comes from + // something like decoding JSON, generated by a weakly typed language + // such as PHP. + input := map[string]interface{}{ + "name": 123, // number => string + "age": "42", // string => number + "emails": map[string]interface{}{}, // empty map => empty array + } + + var result Person + config := &DecoderConfig{ + WeaklyTypedInput: true, + Result: &result, + } + + decoder, err := NewDecoder(config) + if err != nil { + panic(err) + } + + for i := 0; i < b.N; i++ { + decoder.Decode(input) + } +} + +func Benchmark_DecodeMetadata(b *testing.B) { + type Person struct { + Name string + Age int + } + + input := map[string]interface{}{ + "name": "Mitchell", + "age": 91, + "email": "foo@bar.com", + } + + var md Metadata + var result Person + config := &DecoderConfig{ + Metadata: &md, + Result: &result, + } + + decoder, err := NewDecoder(config) + if err != nil { + panic(err) + } + + for i := 0; i < b.N; i++ { + decoder.Decode(input) + } +} + +func Benchmark_DecodeMetadataEmbedded(b *testing.B) { + input := map[string]interface{}{ + "vstring": "foo", + "vunique": "bar", + } + + var md Metadata + var result EmbeddedSquash + config := &DecoderConfig{ + Metadata: &md, + Result: &result, + } + + decoder, err := NewDecoder(config) + if err != nil { + b.Fatalf("err: %s", err) + } + + for i := 0; i < b.N; i++ { + decoder.Decode(input) + } +} + +func Benchmark_DecodeTagged(b *testing.B) { + input := map[string]interface{}{ + "foo": "bar", + "bar": "value", + } + + var result Tagged + for i := 0; i < b.N; i++ { + Decode(input, &result) + } +} diff --git a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_bugs_test.go b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_bugs_test.go new file mode 100644 index 00000000..7054f1ac --- /dev/null +++ b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_bugs_test.go @@ -0,0 +1,47 @@ +package mapstructure + +import "testing" + +// GH-1 +func TestDecode_NilValue(t *testing.T) { + input := map[string]interface{}{ + "vfoo": nil, + "vother": nil, + } + + var result Map + err := Decode(input, &result) + if err != nil { + t.Fatalf("should not error: %s", err) + } + + if result.Vfoo != "" { + t.Fatalf("value should be default: %s", result.Vfoo) + } + + if result.Vother != nil { + t.Fatalf("Vother should be nil: %s", result.Vother) + } +} + +// GH-10 +func TestDecode_mapInterfaceInterface(t *testing.T) { + input := map[interface{}]interface{}{ + "vfoo": nil, + "vother": nil, + } + + var result Map + err := Decode(input, &result) + if err != nil { + t.Fatalf("should not error: %s", err) + } + + if result.Vfoo != "" { + t.Fatalf("value should be default: %s", result.Vfoo) + } + + if result.Vother != nil { + t.Fatalf("Vother should be nil: %s", result.Vother) + } +} diff --git a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_examples_test.go b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_examples_test.go new file mode 100644 index 00000000..f17c214a --- /dev/null +++ b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_examples_test.go @@ -0,0 +1,203 @@ +package mapstructure + +import ( + "fmt" +) + +func ExampleDecode() { + type Person struct { + Name string + Age int + Emails []string + Extra map[string]string + } + + // This input can come from anywhere, but typically comes from + // something like decoding JSON where we're not quite sure of the + // struct initially. + input := map[string]interface{}{ + "name": "Mitchell", + "age": 91, + "emails": []string{"one", "two", "three"}, + "extra": map[string]string{ + "twitter": "mitchellh", + }, + } + + var result Person + err := Decode(input, &result) + if err != nil { + panic(err) + } + + fmt.Printf("%#v", result) + // Output: + // mapstructure.Person{Name:"Mitchell", Age:91, Emails:[]string{"one", "two", "three"}, Extra:map[string]string{"twitter":"mitchellh"}} +} + +func ExampleDecode_errors() { + type Person struct { + Name string + Age int + Emails []string + Extra map[string]string + } + + // This input can come from anywhere, but typically comes from + // something like decoding JSON where we're not quite sure of the + // struct initially. + input := map[string]interface{}{ + "name": 123, + "age": "bad value", + "emails": []int{1, 2, 3}, + } + + var result Person + err := Decode(input, &result) + if err == nil { + panic("should have an error") + } + + fmt.Println(err.Error()) + // Output: + // 5 error(s) decoding: + // + // * 'Age' expected type 'int', got unconvertible type 'string' + // * 'Emails[0]' expected type 'string', got unconvertible type 'int' + // * 'Emails[1]' expected type 'string', got unconvertible type 'int' + // * 'Emails[2]' expected type 'string', got unconvertible type 'int' + // * 'Name' expected type 'string', got unconvertible type 'int' +} + +func ExampleDecode_metadata() { + type Person struct { + Name string + Age int + } + + // This input can come from anywhere, but typically comes from + // something like decoding JSON where we're not quite sure of the + // struct initially. + input := map[string]interface{}{ + "name": "Mitchell", + "age": 91, + "email": "foo@bar.com", + } + + // For metadata, we make a more advanced DecoderConfig so we can + // more finely configure the decoder that is used. In this case, we + // just tell the decoder we want to track metadata. + var md Metadata + var result Person + config := &DecoderConfig{ + Metadata: &md, + Result: &result, + } + + decoder, err := NewDecoder(config) + if err != nil { + panic(err) + } + + if err := decoder.Decode(input); err != nil { + panic(err) + } + + fmt.Printf("Unused keys: %#v", md.Unused) + // Output: + // Unused keys: []string{"email"} +} + +func ExampleDecode_weaklyTypedInput() { + type Person struct { + Name string + Age int + Emails []string + } + + // This input can come from anywhere, but typically comes from + // something like decoding JSON, generated by a weakly typed language + // such as PHP. + input := map[string]interface{}{ + "name": 123, // number => string + "age": "42", // string => number + "emails": map[string]interface{}{}, // empty map => empty array + } + + var result Person + config := &DecoderConfig{ + WeaklyTypedInput: true, + Result: &result, + } + + decoder, err := NewDecoder(config) + if err != nil { + panic(err) + } + + err = decoder.Decode(input) + if err != nil { + panic(err) + } + + fmt.Printf("%#v", result) + // Output: mapstructure.Person{Name:"123", Age:42, Emails:[]string{}} +} + +func ExampleDecode_tags() { + // Note that the mapstructure tags defined in the struct type + // can indicate which fields the values are mapped to. + type Person struct { + Name string `mapstructure:"person_name"` + Age int `mapstructure:"person_age"` + } + + input := map[string]interface{}{ + "person_name": "Mitchell", + "person_age": 91, + } + + var result Person + err := Decode(input, &result) + if err != nil { + panic(err) + } + + fmt.Printf("%#v", result) + // Output: + // mapstructure.Person{Name:"Mitchell", Age:91} +} + +func ExampleDecode_embeddedStruct() { + // Squashing multiple embedded structs is allowed using the squash tag. + // This is demonstrated by creating a composite struct of multiple types + // and decoding into it. In this case, a person can carry with it both + // a Family and a Location, as well as their own FirstName. + type Family struct { + LastName string + } + type Location struct { + City string + } + type Person struct { + Family `mapstructure:",squash"` + Location `mapstructure:",squash"` + FirstName string + } + + input := map[string]interface{}{ + "FirstName": "Mitchell", + "LastName": "Hashimoto", + "City": "San Francisco", + } + + var result Person + err := Decode(input, &result) + if err != nil { + panic(err) + } + + fmt.Printf("%s %s, %s", result.FirstName, result.LastName, result.City) + // Output: + // Mitchell Hashimoto, San Francisco +} diff --git a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_test.go b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_test.go new file mode 100644 index 00000000..1c24e3fb --- /dev/null +++ b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_test.go @@ -0,0 +1,922 @@ +package mapstructure + +import ( + "reflect" + "sort" + "testing" +) + +type Basic struct { + Vstring string + Vint int + Vuint uint + Vbool bool + Vfloat float64 + Vextra string + vsilent bool + Vdata interface{} +} + +type Embedded struct { + Basic + Vunique string +} + +type EmbeddedPointer struct { + *Basic + Vunique string +} + +type EmbeddedSquash struct { + Basic `mapstructure:",squash"` + Vunique string +} + +type Map struct { + Vfoo string + Vother map[string]string +} + +type MapOfStruct struct { + Value map[string]Basic +} + +type Nested struct { + Vfoo string + Vbar Basic +} + +type NestedPointer struct { + Vfoo string + Vbar *Basic +} + +type Slice struct { + Vfoo string + Vbar []string +} + +type SliceOfStruct struct { + Value []Basic +} + +type Tagged struct { + Extra string `mapstructure:"bar,what,what"` + Value string `mapstructure:"foo"` +} + +type TypeConversionResult struct { + IntToFloat float32 + IntToUint uint + IntToBool bool + IntToString string + UintToInt int + UintToFloat float32 + UintToBool bool + UintToString string + BoolToInt int + BoolToUint uint + BoolToFloat float32 + BoolToString string + FloatToInt int + FloatToUint uint + FloatToBool bool + FloatToString string + SliceUint8ToString string + StringToInt int + StringToUint uint + StringToBool bool + StringToFloat float32 + SliceToMap map[string]interface{} + MapToSlice []interface{} +} + +func TestBasicTypes(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "vstring": "foo", + "vint": 42, + "Vuint": 42, + "vbool": true, + "Vfloat": 42.42, + "vsilent": true, + "vdata": 42, + } + + var result Basic + err := Decode(input, &result) + if err != nil { + t.Errorf("got an err: %s", err.Error()) + t.FailNow() + } + + if result.Vstring != "foo" { + t.Errorf("vstring value should be 'foo': %#v", result.Vstring) + } + + if result.Vint != 42 { + t.Errorf("vint value should be 42: %#v", result.Vint) + } + + if result.Vuint != 42 { + t.Errorf("vuint value should be 42: %#v", result.Vuint) + } + + if result.Vbool != true { + t.Errorf("vbool value should be true: %#v", result.Vbool) + } + + if result.Vfloat != 42.42 { + t.Errorf("vfloat value should be 42.42: %#v", result.Vfloat) + } + + if result.Vextra != "" { + t.Errorf("vextra value should be empty: %#v", result.Vextra) + } + + if result.vsilent != false { + t.Error("vsilent should not be set, it is unexported") + } + + if result.Vdata != 42 { + t.Error("vdata should be valid") + } +} + +func TestBasic_IntWithFloat(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "vint": float64(42), + } + + var result Basic + err := Decode(input, &result) + if err != nil { + t.Fatalf("got an err: %s", err) + } +} + +func TestDecode_Embedded(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "vstring": "foo", + "Basic": map[string]interface{}{ + "vstring": "innerfoo", + }, + "vunique": "bar", + } + + var result Embedded + err := Decode(input, &result) + if err != nil { + t.Fatalf("got an err: %s", err.Error()) + } + + if result.Vstring != "innerfoo" { + t.Errorf("vstring value should be 'innerfoo': %#v", result.Vstring) + } + + if result.Vunique != "bar" { + t.Errorf("vunique value should be 'bar': %#v", result.Vunique) + } +} + +func TestDecode_EmbeddedPointer(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "vstring": "foo", + "Basic": map[string]interface{}{ + "vstring": "innerfoo", + }, + "vunique": "bar", + } + + var result EmbeddedPointer + err := Decode(input, &result) + if err == nil { + t.Fatal("should get error") + } +} + +func TestDecode_EmbeddedSquash(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "vstring": "foo", + "vunique": "bar", + } + + var result EmbeddedSquash + err := Decode(input, &result) + if err != nil { + t.Fatalf("got an err: %s", err.Error()) + } + + if result.Vstring != "foo" { + t.Errorf("vstring value should be 'foo': %#v", result.Vstring) + } + + if result.Vunique != "bar" { + t.Errorf("vunique value should be 'bar': %#v", result.Vunique) + } +} + +func TestDecode_DecodeHook(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "vint": "WHAT", + } + + decodeHook := func(from reflect.Kind, to reflect.Kind, v interface{}) (interface{}, error) { + if from == reflect.String && to != reflect.String { + return 5, nil + } + + return v, nil + } + + var result Basic + config := &DecoderConfig{ + DecodeHook: decodeHook, + Result: &result, + } + + decoder, err := NewDecoder(config) + if err != nil { + t.Fatalf("err: %s", err) + } + + err = decoder.Decode(input) + if err != nil { + t.Fatalf("got an err: %s", err) + } + + if result.Vint != 5 { + t.Errorf("vint should be 5: %#v", result.Vint) + } +} + +func TestDecode_DecodeHookType(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "vint": "WHAT", + } + + decodeHook := func(from reflect.Type, to reflect.Type, v interface{}) (interface{}, error) { + if from.Kind() == reflect.String && + to.Kind() != reflect.String { + return 5, nil + } + + return v, nil + } + + var result Basic + config := &DecoderConfig{ + DecodeHook: decodeHook, + Result: &result, + } + + decoder, err := NewDecoder(config) + if err != nil { + t.Fatalf("err: %s", err) + } + + err = decoder.Decode(input) + if err != nil { + t.Fatalf("got an err: %s", err) + } + + if result.Vint != 5 { + t.Errorf("vint should be 5: %#v", result.Vint) + } +} + +func TestDecode_Nil(t *testing.T) { + t.Parallel() + + var input interface{} = nil + result := Basic{ + Vstring: "foo", + } + + err := Decode(input, &result) + if err != nil { + t.Fatalf("err: %s", err) + } + + if result.Vstring != "foo" { + t.Fatalf("bad: %#v", result.Vstring) + } +} + +func TestDecode_NonStruct(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "foo": "bar", + "bar": "baz", + } + + var result map[string]string + err := Decode(input, &result) + if err != nil { + t.Fatalf("err: %s", err) + } + + if result["foo"] != "bar" { + t.Fatal("foo is not bar") + } +} + +func TestDecode_StructMatch(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "vbar": Basic{ + Vstring: "foo", + }, + } + + var result Nested + err := Decode(input, &result) + if err != nil { + t.Fatalf("got an err: %s", err.Error()) + } + + if result.Vbar.Vstring != "foo" { + t.Errorf("bad: %#v", result) + } +} + +func TestDecode_TypeConversion(t *testing.T) { + input := map[string]interface{}{ + "IntToFloat": 42, + "IntToUint": 42, + "IntToBool": 1, + "IntToString": 42, + "UintToInt": 42, + "UintToFloat": 42, + "UintToBool": 42, + "UintToString": 42, + "BoolToInt": true, + "BoolToUint": true, + "BoolToFloat": true, + "BoolToString": true, + "FloatToInt": 42.42, + "FloatToUint": 42.42, + "FloatToBool": 42.42, + "FloatToString": 42.42, + "SliceUint8ToString": []uint8("foo"), + "StringToInt": "42", + "StringToUint": "42", + "StringToBool": "1", + "StringToFloat": "42.42", + "SliceToMap": []interface{}{}, + "MapToSlice": map[string]interface{}{}, + } + + expectedResultStrict := TypeConversionResult{ + IntToFloat: 42.0, + IntToUint: 42, + UintToInt: 42, + UintToFloat: 42, + BoolToInt: 0, + BoolToUint: 0, + BoolToFloat: 0, + FloatToInt: 42, + FloatToUint: 42, + } + + expectedResultWeak := TypeConversionResult{ + IntToFloat: 42.0, + IntToUint: 42, + IntToBool: true, + IntToString: "42", + UintToInt: 42, + UintToFloat: 42, + UintToBool: true, + UintToString: "42", + BoolToInt: 1, + BoolToUint: 1, + BoolToFloat: 1, + BoolToString: "1", + FloatToInt: 42, + FloatToUint: 42, + FloatToBool: true, + FloatToString: "42.42", + SliceUint8ToString: "foo", + StringToInt: 42, + StringToUint: 42, + StringToBool: true, + StringToFloat: 42.42, + SliceToMap: map[string]interface{}{}, + MapToSlice: []interface{}{}, + } + + // Test strict type conversion + var resultStrict TypeConversionResult + err := Decode(input, &resultStrict) + if err == nil { + t.Errorf("should return an error") + } + if !reflect.DeepEqual(resultStrict, expectedResultStrict) { + t.Errorf("expected %v, got: %v", expectedResultStrict, resultStrict) + } + + // Test weak type conversion + var decoder *Decoder + var resultWeak TypeConversionResult + + config := &DecoderConfig{ + WeaklyTypedInput: true, + Result: &resultWeak, + } + + decoder, err = NewDecoder(config) + if err != nil { + t.Fatalf("err: %s", err) + } + + err = decoder.Decode(input) + if err != nil { + t.Fatalf("got an err: %s", err) + } + + if !reflect.DeepEqual(resultWeak, expectedResultWeak) { + t.Errorf("expected \n%#v, got: \n%#v", expectedResultWeak, resultWeak) + } +} + +func TestDecoder_ErrorUnused(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "vstring": "hello", + "foo": "bar", + } + + var result Basic + config := &DecoderConfig{ + ErrorUnused: true, + Result: &result, + } + + decoder, err := NewDecoder(config) + if err != nil { + t.Fatalf("err: %s", err) + } + + err = decoder.Decode(input) + if err == nil { + t.Fatal("expected error") + } +} + +func TestMap(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "vfoo": "foo", + "vother": map[interface{}]interface{}{ + "foo": "foo", + "bar": "bar", + }, + } + + var result Map + err := Decode(input, &result) + if err != nil { + t.Fatalf("got an error: %s", err) + } + + if result.Vfoo != "foo" { + t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo) + } + + if result.Vother == nil { + t.Fatal("vother should not be nil") + } + + if len(result.Vother) != 2 { + t.Error("vother should have two items") + } + + if result.Vother["foo"] != "foo" { + t.Errorf("'foo' key should be foo, got: %#v", result.Vother["foo"]) + } + + if result.Vother["bar"] != "bar" { + t.Errorf("'bar' key should be bar, got: %#v", result.Vother["bar"]) + } +} + +func TestMapOfStruct(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "value": map[string]interface{}{ + "foo": map[string]string{"vstring": "one"}, + "bar": map[string]string{"vstring": "two"}, + }, + } + + var result MapOfStruct + err := Decode(input, &result) + if err != nil { + t.Fatalf("got an err: %s", err) + } + + if result.Value == nil { + t.Fatal("value should not be nil") + } + + if len(result.Value) != 2 { + t.Error("value should have two items") + } + + if result.Value["foo"].Vstring != "one" { + t.Errorf("foo value should be 'one', got: %s", result.Value["foo"].Vstring) + } + + if result.Value["bar"].Vstring != "two" { + t.Errorf("bar value should be 'two', got: %s", result.Value["bar"].Vstring) + } +} + +func TestNestedType(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "vfoo": "foo", + "vbar": map[string]interface{}{ + "vstring": "foo", + "vint": 42, + "vbool": true, + }, + } + + var result Nested + err := Decode(input, &result) + if err != nil { + t.Fatalf("got an err: %s", err.Error()) + } + + if result.Vfoo != "foo" { + t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo) + } + + if result.Vbar.Vstring != "foo" { + t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring) + } + + if result.Vbar.Vint != 42 { + t.Errorf("vint value should be 42: %#v", result.Vbar.Vint) + } + + if result.Vbar.Vbool != true { + t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool) + } + + if result.Vbar.Vextra != "" { + t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra) + } +} + +func TestNestedTypePointer(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "vfoo": "foo", + "vbar": &map[string]interface{}{ + "vstring": "foo", + "vint": 42, + "vbool": true, + }, + } + + var result NestedPointer + err := Decode(input, &result) + if err != nil { + t.Fatalf("got an err: %s", err.Error()) + } + + if result.Vfoo != "foo" { + t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo) + } + + if result.Vbar.Vstring != "foo" { + t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring) + } + + if result.Vbar.Vint != 42 { + t.Errorf("vint value should be 42: %#v", result.Vbar.Vint) + } + + if result.Vbar.Vbool != true { + t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool) + } + + if result.Vbar.Vextra != "" { + t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra) + } +} + +func TestSlice(t *testing.T) { + t.Parallel() + + inputStringSlice := map[string]interface{}{ + "vfoo": "foo", + "vbar": []string{"foo", "bar", "baz"}, + } + + inputStringSlicePointer := map[string]interface{}{ + "vfoo": "foo", + "vbar": &[]string{"foo", "bar", "baz"}, + } + + outputStringSlice := &Slice{ + "foo", + []string{"foo", "bar", "baz"}, + } + + testSliceInput(t, inputStringSlice, outputStringSlice) + testSliceInput(t, inputStringSlicePointer, outputStringSlice) +} + +func TestInvalidSlice(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "vfoo": "foo", + "vbar": 42, + } + + result := Slice{} + err := Decode(input, &result) + if err == nil { + t.Errorf("expected failure") + } +} + +func TestSliceOfStruct(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "value": []map[string]interface{}{ + {"vstring": "one"}, + {"vstring": "two"}, + }, + } + + var result SliceOfStruct + err := Decode(input, &result) + if err != nil { + t.Fatalf("got unexpected error: %s", err) + } + + if len(result.Value) != 2 { + t.Fatalf("expected two values, got %d", len(result.Value)) + } + + if result.Value[0].Vstring != "one" { + t.Errorf("first value should be 'one', got: %s", result.Value[0].Vstring) + } + + if result.Value[1].Vstring != "two" { + t.Errorf("second value should be 'two', got: %s", result.Value[1].Vstring) + } +} + +func TestInvalidType(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "vstring": 42, + } + + var result Basic + err := Decode(input, &result) + if err == nil { + t.Fatal("error should exist") + } + + derr, ok := err.(*Error) + if !ok { + t.Fatalf("error should be kind of Error, instead: %#v", err) + } + + if derr.Errors[0] != "'Vstring' expected type 'string', got unconvertible type 'int'" { + t.Errorf("got unexpected error: %s", err) + } + + inputNegIntUint := map[string]interface{}{ + "vuint": -42, + } + + err = Decode(inputNegIntUint, &result) + if err == nil { + t.Fatal("error should exist") + } + + derr, ok = err.(*Error) + if !ok { + t.Fatalf("error should be kind of Error, instead: %#v", err) + } + + if derr.Errors[0] != "cannot parse 'Vuint', -42 overflows uint" { + t.Errorf("got unexpected error: %s", err) + } + + inputNegFloatUint := map[string]interface{}{ + "vuint": -42.0, + } + + err = Decode(inputNegFloatUint, &result) + if err == nil { + t.Fatal("error should exist") + } + + derr, ok = err.(*Error) + if !ok { + t.Fatalf("error should be kind of Error, instead: %#v", err) + } + + if derr.Errors[0] != "cannot parse 'Vuint', -42.000000 overflows uint" { + t.Errorf("got unexpected error: %s", err) + } +} + +func TestMetadata(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "vfoo": "foo", + "vbar": map[string]interface{}{ + "vstring": "foo", + "Vuint": 42, + "foo": "bar", + }, + "bar": "nil", + } + + var md Metadata + var result Nested + config := &DecoderConfig{ + Metadata: &md, + Result: &result, + } + + decoder, err := NewDecoder(config) + if err != nil { + t.Fatalf("err: %s", err) + } + + err = decoder.Decode(input) + if err != nil { + t.Fatalf("err: %s", err.Error()) + } + + expectedKeys := []string{"Vbar", "Vbar.Vstring", "Vbar.Vuint", "Vfoo"} + sort.Strings(md.Keys) + if !reflect.DeepEqual(md.Keys, expectedKeys) { + t.Fatalf("bad keys: %#v", md.Keys) + } + + expectedUnused := []string{"Vbar.foo", "bar"} + if !reflect.DeepEqual(md.Unused, expectedUnused) { + t.Fatalf("bad unused: %#v", md.Unused) + } +} + +func TestMetadata_Embedded(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "vstring": "foo", + "vunique": "bar", + } + + var md Metadata + var result EmbeddedSquash + config := &DecoderConfig{ + Metadata: &md, + Result: &result, + } + + decoder, err := NewDecoder(config) + if err != nil { + t.Fatalf("err: %s", err) + } + + err = decoder.Decode(input) + if err != nil { + t.Fatalf("err: %s", err.Error()) + } + + expectedKeys := []string{"Vstring", "Vunique"} + + sort.Strings(md.Keys) + if !reflect.DeepEqual(md.Keys, expectedKeys) { + t.Fatalf("bad keys: %#v", md.Keys) + } + + expectedUnused := []string{} + if !reflect.DeepEqual(md.Unused, expectedUnused) { + t.Fatalf("bad unused: %#v", md.Unused) + } +} + +func TestNonPtrValue(t *testing.T) { + t.Parallel() + + err := Decode(map[string]interface{}{}, Basic{}) + if err == nil { + t.Fatal("error should exist") + } + + if err.Error() != "result must be a pointer" { + t.Errorf("got unexpected error: %s", err) + } +} + +func TestTagged(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "foo": "bar", + "bar": "value", + } + + var result Tagged + err := Decode(input, &result) + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + + if result.Value != "bar" { + t.Errorf("value should be 'bar', got: %#v", result.Value) + } + + if result.Extra != "value" { + t.Errorf("extra should be 'value', got: %#v", result.Extra) + } +} + +func TestWeakDecode(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "foo": "4", + "bar": "value", + } + + var result struct { + Foo int + Bar string + } + + if err := WeakDecode(input, &result); err != nil { + t.Fatalf("err: %s", err) + } + if result.Foo != 4 { + t.Fatalf("bad: %#v", result) + } + if result.Bar != "value" { + t.Fatalf("bad: %#v", result) + } +} + +func testSliceInput(t *testing.T, input map[string]interface{}, expected *Slice) { + var result Slice + err := Decode(input, &result) + if err != nil { + t.Fatalf("got error: %s", err) + } + + if result.Vfoo != expected.Vfoo { + t.Errorf("Vfoo expected '%s', got '%s'", expected.Vfoo, result.Vfoo) + } + + if result.Vbar == nil { + t.Fatalf("Vbar a slice, got '%#v'", result.Vbar) + } + + if len(result.Vbar) != len(expected.Vbar) { + t.Errorf("Vbar length should be %d, got %d", len(expected.Vbar), len(result.Vbar)) + } + + for i, v := range result.Vbar { + if v != expected.Vbar[i] { + t.Errorf( + "Vbar[%d] should be '%#v', got '%#v'", + i, expected.Vbar[i], v) + } + } +} diff --git a/Godeps/_workspace/src/github.com/spf13/cast/.gitignore b/Godeps/_workspace/src/github.com/spf13/cast/.gitignore new file mode 100644 index 00000000..83656241 --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/cast/.gitignore @@ -0,0 +1,23 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test diff --git a/Godeps/_workspace/src/github.com/spf13/cast/LICENSE b/Godeps/_workspace/src/github.com/spf13/cast/LICENSE new file mode 100644 index 00000000..4527efb9 --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/cast/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Steve Francia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/spf13/cast/README.md b/Godeps/_workspace/src/github.com/spf13/cast/README.md new file mode 100644 index 00000000..af7a1fdc --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/cast/README.md @@ -0,0 +1,72 @@ +cast +==== + +Easy and safe casting from one type to another in Go + +Don’t Panic! ... Cast + +## What is Cast? + +Cast is a library to convert between different go types in a consistent and easy way. + +Cast provides simple functions to easily convert a number to a string, an +interface into a bool, etc. Cast does this intelligently when an obvious +conversion is possible. It doesn’t make any attempts to guess what you meant, +for example you can only convert a string to an int when it is a string +representation of an int such as “8”. Cast was developed for use in +[Hugo](http://hugo.spf13.com), a website engine which uses YAML, TOML or JSON +for meta data. + +## Why use Cast? + +When working with dynamic data in Go you often need to cast or convert the data +from one type into another. Cast goes beyond just using type assertion (though +it uses that when possible) to provide a very straightforward and convenient +library. + +If you are working with interfaces to handle things like dynamic content +you’ll need an easy way to convert an interface into a given type. This +is the library for you. + +If you are taking in data from YAML, TOML or JSON or other formats which lack +full types, then Cast is the library for you. + +## Usage + +Cast provides a handful of To_____ methods. These methods will always return +the desired type. **If input is provided that will not convert to that type, the +0 or nil value for that type will be returned**. + +Cast also provides identical methods To_____E. These return the same result as +the To_____ methods, plus an additional error which tells you if it successfully +converted. Using these methods you can tell the difference between when the +input matched the zero value or when the conversion failed and the zero value +was returned. + +The following examples are merely a sample of what is available. Please review +the code for a complete set. + +### Example ‘ToString’: + + cast.ToString("mayonegg") // "mayonegg" + cast.ToString(8) // "8" + cast.ToString(8.31) // "8.31" + cast.ToString([]byte("one time")) // "one time" + cast.ToString(nil) // "" + + var foo interface{} = "one more time" + cast.ToString(foo) // "one more time" + + +### Example ‘ToInt’: + + cast.ToInt(8) // 8 + cast.ToInt(8.31) // 8 + cast.ToInt("8") // 8 + cast.ToInt(true) // 1 + cast.ToInt(false) // 0 + + var eight interface{} = 8 + cast.ToInt(eight) // 8 + cast.ToInt(nil) // 0 + diff --git a/Godeps/_workspace/src/github.com/spf13/cast/cast.go b/Godeps/_workspace/src/github.com/spf13/cast/cast.go new file mode 100644 index 00000000..1dde519f --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/cast/cast.go @@ -0,0 +1,68 @@ +// Copyright © 2014 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package cast + +import "time" + +func ToBool(i interface{}) bool { + v, _ := ToBoolE(i) + return v +} + +func ToTime(i interface{}) time.Time { + v, _ := ToTimeE(i) + return v +} + +func ToDuration(i interface{}) time.Duration { + v, _ := ToDurationE(i) + return v +} + +func ToFloat64(i interface{}) float64 { + v, _ := ToFloat64E(i) + return v +} + +func ToInt(i interface{}) int { + v, _ := ToIntE(i) + return v +} + +func ToString(i interface{}) string { + v, _ := ToStringE(i) + return v +} + +func ToStringMapString(i interface{}) map[string]string { + v, _ := ToStringMapStringE(i) + return v +} + +func ToStringMapBool(i interface{}) map[string]bool { + v, _ := ToStringMapBoolE(i) + return v +} + +func ToStringMap(i interface{}) map[string]interface{} { + v, _ := ToStringMapE(i) + return v +} + +func ToSlice(i interface{}) []interface{} { + v, _ := ToSliceE(i) + return v +} + +func ToStringSlice(i interface{}) []string { + v, _ := ToStringSliceE(i) + return v +} + +func ToIntSlice(i interface{}) []int { + v, _ := ToIntSliceE(i) + return v +} diff --git a/Godeps/_workspace/src/github.com/spf13/cast/cast_test.go b/Godeps/_workspace/src/github.com/spf13/cast/cast_test.go new file mode 100644 index 00000000..3fa717fe --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/cast/cast_test.go @@ -0,0 +1,117 @@ +// Copyright © 2014 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package cast + +import ( + "testing" + + "html/template" + + "github.com/stretchr/testify/assert" +) + +func TestToInt(t *testing.T) { + var eight interface{} = 8 + assert.Equal(t, ToInt(8), 8) + assert.Equal(t, ToInt(8.31), 8) + assert.Equal(t, ToInt("8"), 8) + assert.Equal(t, ToInt(true), 1) + assert.Equal(t, ToInt(false), 0) + assert.Equal(t, ToInt(eight), 8) +} + +func TestToFloat64(t *testing.T) { + var eight interface{} = 8 + assert.Equal(t, ToFloat64(8), 8.00) + assert.Equal(t, ToFloat64(8.31), 8.31) + assert.Equal(t, ToFloat64("8.31"), 8.31) + assert.Equal(t, ToFloat64(eight), 8.0) +} + +func TestToString(t *testing.T) { + var foo interface{} = "one more time" + assert.Equal(t, ToString(8), "8") + assert.Equal(t, ToString(8.12), "8.12") + assert.Equal(t, ToString([]byte("one time")), "one time") + assert.Equal(t, ToString(template.HTML("one time")), "one time") + assert.Equal(t, ToString(foo), "one more time") + assert.Equal(t, ToString(nil), "") +} + +type foo struct { + val string +} + +func (x foo) String() string { + return x.val +} + +func TestStringerToString(t *testing.T) { + + var x foo + x.val = "bar" + assert.Equal(t, "bar", ToString(x)) +} + +type fu struct { + val string +} + +func (x fu) Error() string { + return x.val +} + +func TestErrorToString(t *testing.T) { + var x fu + x.val = "bar" + assert.Equal(t, "bar", ToString(x)) +} + +func TestMaps(t *testing.T) { + var taxonomies = map[interface{}]interface{}{"tag": "tags", "group": "groups"} + var stringMapBool = map[interface{}]interface{}{"v1": true, "v2": false} + assert.Equal(t, ToStringMap(taxonomies), map[string]interface{}{"tag": "tags", "group": "groups"}) + assert.Equal(t, ToStringMapBool(stringMapBool), map[string]bool{"v1": true, "v2": false}) +} + +func TestSlices(t *testing.T) { + assert.Equal(t, []string{"a", "b"}, ToStringSlice([]string{"a", "b"})) + assert.Equal(t, []string{"1", "3"}, ToStringSlice([]interface{}{1, 3})) + assert.Equal(t, []int{1, 3}, ToIntSlice([]int{1, 3})) + assert.Equal(t, []int{1, 3}, ToIntSlice([]interface{}{1.2, 3.2})) + assert.Equal(t, []int{2, 3}, ToIntSlice([]string{"2", "3"})) + assert.Equal(t, []int{2, 3}, ToIntSlice([2]string{"2", "3"})) +} + +func TestToBool(t *testing.T) { + assert.Equal(t, ToBool(0), false) + assert.Equal(t, ToBool(nil), false) + assert.Equal(t, ToBool("false"), false) + assert.Equal(t, ToBool("FALSE"), false) + assert.Equal(t, ToBool("False"), false) + assert.Equal(t, ToBool("f"), false) + assert.Equal(t, ToBool("F"), false) + assert.Equal(t, ToBool(false), false) + assert.Equal(t, ToBool("foo"), false) + + assert.Equal(t, ToBool("true"), true) + assert.Equal(t, ToBool("TRUE"), true) + assert.Equal(t, ToBool("True"), true) + assert.Equal(t, ToBool("t"), true) + assert.Equal(t, ToBool("T"), true) + assert.Equal(t, ToBool(1), true) + assert.Equal(t, ToBool(true), true) + assert.Equal(t, ToBool(-1), true) +} + +func TestIndirectPointers(t *testing.T) { + x := 13 + y := &x + z := &y + + assert.Equal(t, ToInt(y), 13) + assert.Equal(t, ToInt(z), 13) +} diff --git a/Godeps/_workspace/src/github.com/spf13/cast/caste.go b/Godeps/_workspace/src/github.com/spf13/cast/caste.go new file mode 100644 index 00000000..16b67659 --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/cast/caste.go @@ -0,0 +1,378 @@ +// Copyright © 2014 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package cast + +import ( + "errors" + "fmt" + "html/template" + "reflect" + "strconv" + "strings" + "time" + + jww "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/spf13/jwalterweatherman" +) + +func ToTimeE(i interface{}) (tim time.Time, err error) { + i = indirect(i) + jww.DEBUG.Println("ToTimeE called on type:", reflect.TypeOf(i)) + + switch s := i.(type) { + case time.Time: + return s, nil + case string: + d, e := StringToDate(s) + if e == nil { + return d, nil + } + return time.Time{}, fmt.Errorf("Could not parse Date/Time format: %v\n", e) + default: + return time.Time{}, fmt.Errorf("Unable to Cast %#v to Time\n", i) + } +} + +func ToDurationE(i interface{}) (d time.Duration, err error) { + i = indirect(i) + jww.DEBUG.Println("ToDurationE called on type:", reflect.TypeOf(i)) + + switch s := i.(type) { + case time.Duration: + return s, nil + case string: + d, err = time.ParseDuration(s) + return + default: + err = fmt.Errorf("Unable to Cast %#v to Duration\n", i) + return + } +} + +func ToBoolE(i interface{}) (bool, error) { + i = indirect(i) + jww.DEBUG.Println("ToBoolE called on type:", reflect.TypeOf(i)) + + switch b := i.(type) { + case bool: + return b, nil + case nil: + return false, nil + case int: + if i.(int) != 0 { + return true, nil + } + return false, nil + case string: + return strconv.ParseBool(i.(string)) + default: + return false, fmt.Errorf("Unable to Cast %#v to bool", i) + } +} + +func ToFloat64E(i interface{}) (float64, error) { + i = indirect(i) + jww.DEBUG.Println("ToFloat64E called on type:", reflect.TypeOf(i)) + + switch s := i.(type) { + case float64: + return s, nil + case float32: + return float64(s), nil + case int64: + return float64(s), nil + case int32: + return float64(s), nil + case int16: + return float64(s), nil + case int8: + return float64(s), nil + case int: + return float64(s), nil + case string: + v, err := strconv.ParseFloat(s, 64) + if err == nil { + return float64(v), nil + } else { + return 0.0, fmt.Errorf("Unable to Cast %#v to float", i) + } + default: + return 0.0, fmt.Errorf("Unable to Cast %#v to float", i) + } +} + +func ToIntE(i interface{}) (int, error) { + i = indirect(i) + jww.DEBUG.Println("ToIntE called on type:", reflect.TypeOf(i)) + + switch s := i.(type) { + case int: + return s, nil + case int64: + return int(s), nil + case int32: + return int(s), nil + case int16: + return int(s), nil + case int8: + return int(s), nil + case string: + v, err := strconv.ParseInt(s, 0, 0) + if err == nil { + return int(v), nil + } else { + return 0, fmt.Errorf("Unable to Cast %#v to int", i) + } + case float64: + return int(s), nil + case bool: + if bool(s) { + return 1, nil + } else { + return 0, nil + } + case nil: + return 0, nil + default: + return 0, fmt.Errorf("Unable to Cast %#v to int", i) + } +} + +// From html/template/content.go +// Copyright 2011 The Go Authors. All rights reserved. +// indirect returns the value, after dereferencing as many times +// as necessary to reach the base type (or nil). +func indirect(a interface{}) interface{} { + if a == nil { + return nil + } + if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr { + // Avoid creating a reflect.Value if it's not a pointer. + return a + } + v := reflect.ValueOf(a) + for v.Kind() == reflect.Ptr && !v.IsNil() { + v = v.Elem() + } + return v.Interface() +} + +// From html/template/content.go +// Copyright 2011 The Go Authors. All rights reserved. +// indirectToStringerOrError returns the value, after dereferencing as many times +// as necessary to reach the base type (or nil) or an implementation of fmt.Stringer +// or error, +func indirectToStringerOrError(a interface{}) interface{} { + if a == nil { + return nil + } + + var errorType = reflect.TypeOf((*error)(nil)).Elem() + var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() + + v := reflect.ValueOf(a) + for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() { + v = v.Elem() + } + return v.Interface() +} + +func ToStringE(i interface{}) (string, error) { + i = indirectToStringerOrError(i) + jww.DEBUG.Println("ToStringE called on type:", reflect.TypeOf(i)) + + switch s := i.(type) { + case string: + return s, nil + case float64: + return strconv.FormatFloat(i.(float64), 'f', -1, 64), nil + case int: + return strconv.FormatInt(int64(i.(int)), 10), nil + case []byte: + return string(s), nil + case template.HTML: + return string(s), nil + case nil: + return "", nil + case fmt.Stringer: + return s.String(), nil + case error: + return s.Error(), nil + default: + return "", fmt.Errorf("Unable to Cast %#v to string", i) + } +} + +func ToStringMapStringE(i interface{}) (map[string]string, error) { + jww.DEBUG.Println("ToStringMapStringE called on type:", reflect.TypeOf(i)) + + var m = map[string]string{} + + switch v := i.(type) { + case map[interface{}]interface{}: + for k, val := range v { + m[ToString(k)] = ToString(val) + } + return m, nil + case map[string]interface{}: + for k, val := range v { + m[ToString(k)] = ToString(val) + } + return m, nil + case map[string]string: + return v, nil + default: + return m, fmt.Errorf("Unable to Cast %#v to map[string]string", i) + } + return m, fmt.Errorf("Unable to Cast %#v to map[string]string", i) +} + +func ToStringMapBoolE(i interface{}) (map[string]bool, error) { + jww.DEBUG.Println("ToStringMapBoolE called on type:", reflect.TypeOf(i)) + + var m = map[string]bool{} + + switch v := i.(type) { + case map[interface{}]interface{}: + for k, val := range v { + m[ToString(k)] = ToBool(val) + } + return m, nil + case map[string]interface{}: + for k, val := range v { + m[ToString(k)] = ToBool(val) + } + return m, nil + case map[string]bool: + return v, nil + default: + return m, fmt.Errorf("Unable to Cast %#v to map[string]bool", i) + } + return m, fmt.Errorf("Unable to Cast %#v to map[string]bool", i) +} + +func ToStringMapE(i interface{}) (map[string]interface{}, error) { + jww.DEBUG.Println("ToStringMapE called on type:", reflect.TypeOf(i)) + + var m = map[string]interface{}{} + + switch v := i.(type) { + case map[interface{}]interface{}: + for k, val := range v { + m[ToString(k)] = val + } + return m, nil + case map[string]interface{}: + return v, nil + default: + return m, fmt.Errorf("Unable to Cast %#v to map[string]interface{}", i) + } + + return m, fmt.Errorf("Unable to Cast %#v to map[string]interface{}", i) +} + +func ToSliceE(i interface{}) ([]interface{}, error) { + jww.DEBUG.Println("ToSliceE called on type:", reflect.TypeOf(i)) + + var s []interface{} + + switch v := i.(type) { + case []interface{}: + for _, u := range v { + s = append(s, u) + } + return s, nil + case []map[string]interface{}: + for _, u := range v { + s = append(s, u) + } + return s, nil + default: + return s, fmt.Errorf("Unable to Cast %#v of type %v to []interface{}", i, reflect.TypeOf(i)) + } + + return s, fmt.Errorf("Unable to Cast %#v to []interface{}", i) +} + +func ToStringSliceE(i interface{}) ([]string, error) { + jww.DEBUG.Println("ToStringSliceE called on type:", reflect.TypeOf(i)) + + var a []string + + switch v := i.(type) { + case []interface{}: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []string: + return v, nil + case string: + return strings.Fields(v), nil + default: + return a, fmt.Errorf("Unable to Cast %#v to []string", i) + } + + return a, fmt.Errorf("Unable to Cast %#v to []string", i) +} + +func ToIntSliceE(i interface{}) ([]int, error) { + jww.DEBUG.Println("ToIntSliceE called on type:", reflect.TypeOf(i)) + + if i == nil { + return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i) + } + + switch v := i.(type) { + case []int: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]int, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := ToIntE(s.Index(j).Interface()) + if err != nil { + return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i) + } + a[j] = val + } + return a, nil + default: + return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i) + } + + return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i) +} + +func StringToDate(s string) (time.Time, error) { + return parseDateWith(s, []string{ + time.RFC3339, + "2006-01-02T15:04:05", // iso8601 without timezone + time.RFC1123Z, + time.RFC1123, + time.RFC822Z, + time.RFC822, + time.ANSIC, + time.UnixDate, + time.RubyDate, + "2006-01-02 15:04:05Z07:00", + "02 Jan 06 15:04 MST", + "2006-01-02", + "02 Jan 2006", + }) +} + +func parseDateWith(s string, dates []string) (d time.Time, e error) { + for _, dateType := range dates { + if d, e = time.Parse(dateType, s); e == nil { + return + } + } + return d, errors.New(fmt.Sprintf("Unable to parse date: %s", s)) +} diff --git a/Godeps/_workspace/src/github.com/spf13/jwalterweatherman/.gitignore b/Godeps/_workspace/src/github.com/spf13/jwalterweatherman/.gitignore new file mode 100644 index 00000000..00268614 --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/jwalterweatherman/.gitignore @@ -0,0 +1,22 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/Godeps/_workspace/src/github.com/spf13/jwalterweatherman/LICENSE b/Godeps/_workspace/src/github.com/spf13/jwalterweatherman/LICENSE new file mode 100644 index 00000000..4527efb9 --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/jwalterweatherman/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Steve Francia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/spf13/jwalterweatherman/README.md b/Godeps/_workspace/src/github.com/spf13/jwalterweatherman/README.md new file mode 100644 index 00000000..2f6c9c84 --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/jwalterweatherman/README.md @@ -0,0 +1,158 @@ +jWalterWeatherman +================= + +Seamless printing to the terminal (stdout) and logging to a io.Writer +(file) that’s as easy to use as fmt.Println. + +![Always Leave A Note](http://spf13.github.com/jwalterweatherman/and_that__s_why_you_always_leave_a_note_by_jonnyetc-d57q7um.jpg) +Graphic by [JonnyEtc](http://jonnyetc.deviantart.com/art/And-That-s-Why-You-Always-Leave-a-Note-315311422) + +JWW is primarily a wrapper around the excellent standard log library. It +provides a few advantages over using the standard log library alone. + +1. Ready to go out of the box. +2. One library for both printing to the terminal and logging (to files). +3. Really easy to log to either a temp file or a file you specify. + + +I really wanted a very straightforward library that could seamlessly do +the following things. + +1. Replace all the println, printf, etc statements thought my code with + something more useful +2. Allow the user to easily control what levels are printed to stdout +3. Allow the user to easily control what levels are logged +4. Provide an easy mechanism (like fmt.Println) to print info to the user + which can be easily logged as well +5. Due to 2 & 3 provide easy verbose mode for output and logs +6. Not have any unnecessary initialization cruft. Just use it. + +# Usage + +## Step 1. Use it +Put calls throughout your source based on type of feedback. +No initialization or setup needs to happen. Just start calling things. + +Available Loggers are: + + * TRACE + * DEBUG + * INFO + * WARN + * ERROR + * CRITICAL + * FATAL + +These each are loggers based on the log standard library and follow the +standard usage. Eg.. + +```go + import ( + jww "github.com/spf13/jwalterweatherman" + ) + + ... + + if err != nil { + + // This is a pretty serious error and the user should know about + // it. It will be printed to the terminal as well as logged under the + // default thresholds. + + jww.ERROR.Println(err) + } + + if err2 != nil { + // This error isn’t going to materially change the behavior of the + // application, but it’s something that may not be what the user + // expects. Under the default thresholds, Warn will be logged, but + // not printed to the terminal. + + jww.WARN.Println(err2) + } + + // Information that’s relevant to what’s happening, but not very + // important for the user. Under the default thresholds this will be + // discarded. + + jww.INFO.Printf("information %q", response) + +``` + +_Why 7 levels?_ + +Maybe you think that 7 levels are too much for any application... and you +are probably correct. Just because there are seven levels doesn’t mean +that you should be using all 7 levels. Pick the right set for your needs. +Remember they only have to mean something to your project. + +## Step 2. Optionally configure JWW + +Under the default thresholds : + + * Debug, Trace & Info goto /dev/null + * Warn and above is logged (when a log file/io.Writer is provided) + * Error and above is printed to the terminal (stdout) + +### Changing the thresholds + +The threshold can be changed at any time, but will only affect calls that +execute after the change was made. + +This is very useful if your application has a verbose mode. Of course you +can decide what verbose means to you or even have multiple levels of +verbosity. + + +```go + import ( + jww "github.com/spf13/jwalterweatherman" + ) + + if Verbose { + jww.SetLogThreshold(jww.LevelTrace) + jww.SetStdoutThreshold(jww.LevelInfo) + } +``` + +### Using a temp log file + +JWW conveniently creates a temporary file and sets the log Handle to +a io.Writer created for it. You should call this early in your application +initialization routine as it will only log calls made after it is executed. +When this option is used, the library will fmt.Println where to find the +log file. + +```go + import ( + jww "github.com/spf13/jwalterweatherman" + ) + + jww.UseTempLogFile("YourAppName") + +``` + +### Setting a log file + +JWW can log to any file you provide a path to (provided it’s writable). +Will only append to this file. + + +```go + import ( + jww "github.com/spf13/jwalterweatherman" + ) + + jww.SetLogFile("/path/to/logfile") + +``` + + +# More information + +This is an early release. I’ve been using it for a while and this is the +third interface I’ve tried. I like this one pretty well, but no guarantees +that it won’t change a bit. + +I wrote this for use in [hugo](http://hugo.spf13.com). If you are looking +for a static website engine that’s super fast please checkout Hugo. diff --git a/Godeps/_workspace/src/github.com/spf13/jwalterweatherman/jww_test.go b/Godeps/_workspace/src/github.com/spf13/jwalterweatherman/jww_test.go new file mode 100644 index 00000000..b6d118aa --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/jwalterweatherman/jww_test.go @@ -0,0 +1,56 @@ +// Copyright © 2014 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package jwalterweatherman + +import ( + "bytes" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestLevels(t *testing.T) { + SetStdoutThreshold(LevelError) + assert.Equal(t, StdoutThreshold(), LevelError) + SetLogThreshold(LevelCritical) + assert.Equal(t, LogThreshold(), LevelCritical) + assert.NotEqual(t, StdoutThreshold(), LevelCritical) + SetStdoutThreshold(LevelWarn) + assert.Equal(t, StdoutThreshold(), LevelWarn) +} + +func TestDefaultLogging(t *testing.T) { + outputBuf := new(bytes.Buffer) + logBuf := new(bytes.Buffer) + LogHandle = logBuf + OutHandle = outputBuf + + SetLogThreshold(LevelWarn) + SetStdoutThreshold(LevelError) + + FATAL.Println("fatal err") + CRITICAL.Println("critical err") + ERROR.Println("an error") + WARN.Println("a warning") + INFO.Println("information") + DEBUG.Println("debugging info") + TRACE.Println("trace") + + assert.Contains(t, logBuf.String(), "fatal err") + assert.Contains(t, logBuf.String(), "critical err") + assert.Contains(t, logBuf.String(), "an error") + assert.Contains(t, logBuf.String(), "a warning") + assert.NotContains(t, logBuf.String(), "information") + assert.NotContains(t, logBuf.String(), "debugging info") + assert.NotContains(t, logBuf.String(), "trace") + + assert.Contains(t, outputBuf.String(), "fatal err") + assert.Contains(t, outputBuf.String(), "critical err") + assert.Contains(t, outputBuf.String(), "an error") + assert.NotContains(t, outputBuf.String(), "a warning") + assert.NotContains(t, outputBuf.String(), "information") + assert.NotContains(t, outputBuf.String(), "debugging info") + assert.NotContains(t, outputBuf.String(), "trace") +} diff --git a/Godeps/_workspace/src/github.com/spf13/jwalterweatherman/thatswhyyoualwaysleaveanote.go b/Godeps/_workspace/src/github.com/spf13/jwalterweatherman/thatswhyyoualwaysleaveanote.go new file mode 100644 index 00000000..2f3d721b --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/jwalterweatherman/thatswhyyoualwaysleaveanote.go @@ -0,0 +1,183 @@ +// Copyright © 2014 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package jwalterweatherman + +import ( + "fmt" + "io" + "io/ioutil" + "log" + "os" +) + +// Level describes the chosen log level between +// debug and critical. +type Level int + +type NotePad struct { + Handle io.Writer + Level Level + Prefix string + Logger **log.Logger +} + +// Feedback is special. It writes plainly to the output while +// logging with the standard extra information (date, file, etc) +// Only Println and Printf are currently provided for this +type Feedback struct{} + +const ( + LevelTrace Level = iota + LevelDebug + LevelInfo + LevelWarn + LevelError + LevelCritical + LevelFatal + DefaultLogThreshold = LevelWarn + DefaultStdoutThreshold = LevelError +) + +var ( + TRACE *log.Logger + DEBUG *log.Logger + INFO *log.Logger + WARN *log.Logger + ERROR *log.Logger + CRITICAL *log.Logger + FATAL *log.Logger + LOG *log.Logger + FEEDBACK Feedback + LogHandle io.Writer = ioutil.Discard + OutHandle io.Writer = os.Stdout + BothHandle io.Writer = io.MultiWriter(LogHandle, OutHandle) + NotePads []*NotePad = []*NotePad{trace, debug, info, warn, err, critical, fatal} + + trace *NotePad = &NotePad{Level: LevelTrace, Handle: os.Stdout, Logger: &TRACE, Prefix: "TRACE: "} + debug *NotePad = &NotePad{Level: LevelDebug, Handle: os.Stdout, Logger: &DEBUG, Prefix: "DEBUG: "} + info *NotePad = &NotePad{Level: LevelInfo, Handle: os.Stdout, Logger: &INFO, Prefix: "INFO: "} + warn *NotePad = &NotePad{Level: LevelWarn, Handle: os.Stdout, Logger: &WARN, Prefix: "WARN: "} + err *NotePad = &NotePad{Level: LevelError, Handle: os.Stdout, Logger: &ERROR, Prefix: "ERROR: "} + critical *NotePad = &NotePad{Level: LevelCritical, Handle: os.Stdout, Logger: &CRITICAL, Prefix: "CRITICAL: "} + fatal *NotePad = &NotePad{Level: LevelFatal, Handle: os.Stdout, Logger: &FATAL, Prefix: "FATAL: "} + logThreshold Level = DefaultLogThreshold + outputThreshold Level = DefaultStdoutThreshold +) + +func init() { + SetStdoutThreshold(DefaultStdoutThreshold) +} + +// initialize will setup the jWalterWeatherman standard approach of providing the user +// some feedback and logging a potentially different amount based on independent log and output thresholds. +// By default the output has a lower threshold than logged +// Don't use if you have manually set the Handles of the different levels as it will overwrite them. +func initialize() { + BothHandle = io.MultiWriter(LogHandle, OutHandle) + + for _, n := range NotePads { + if n.Level < outputThreshold && n.Level < logThreshold { + n.Handle = ioutil.Discard + } else if n.Level >= outputThreshold && n.Level >= logThreshold { + n.Handle = BothHandle + } else if n.Level >= outputThreshold && n.Level < logThreshold { + n.Handle = OutHandle + } else { + n.Handle = LogHandle + } + } + + for _, n := range NotePads { + *n.Logger = log.New(n.Handle, n.Prefix, log.Ldate) + } + + LOG = log.New(LogHandle, + "LOG: ", + log.Ldate|log.Ltime|log.Lshortfile) +} + +// Level returns the current global log threshold. +func LogThreshold() Level { + return logThreshold +} + +// Level returns the current global output threshold. +func StdoutThreshold() Level { + return outputThreshold +} + +// Ensures that the level provided is within the bounds of available levels +func levelCheck(level Level) Level { + switch { + case level <= LevelTrace: + return LevelTrace + case level >= LevelFatal: + return LevelFatal + default: + return level + } +} + +// Establishes a threshold where anything matching or above will be logged +func SetLogThreshold(level Level) { + logThreshold = levelCheck(level) + initialize() +} + +// Establishes a threshold where anything matching or above will be output +func SetStdoutThreshold(level Level) { + outputThreshold = levelCheck(level) + initialize() +} + +// Conveniently Sets the Log Handle to a io.writer created for the file behind the given filepath +// Will only append to this file +func SetLogFile(path string) { + file, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666) + if err != nil { + CRITICAL.Println("Failed to open log file:", path, err) + os.Exit(-1) + } + fmt.Println("Logging to", file.Name()) + + LogHandle = file + initialize() +} + +// Conveniently Creates a temporary file and sets the Log Handle to a io.writer created for it +func UseTempLogFile(prefix string) { + file, err := ioutil.TempFile(os.TempDir(), prefix) + if err != nil { + CRITICAL.Println(err) + } + + fmt.Println("Logging to", file.Name()) + + LogHandle = file + initialize() +} + +// Disables logging for the entire JWW system +func DiscardLogging() { + LogHandle = ioutil.Discard + initialize() +} + +// Feedback is special. It writes plainly to the output while +// logging with the standard extra information (date, file, etc) +// Only Println and Printf are currently provided for this +func (fb *Feedback) Println(v ...interface{}) { + fmt.Println(v...) + LOG.Println(v...) +} + +// Feedback is special. It writes plainly to the output while +// logging with the standard extra information (date, file, etc) +// Only Println and Printf are currently provided for this +func (fb *Feedback) Printf(format string, v ...interface{}) { + fmt.Printf(format, v...) + LOG.Printf(format, v...) +} diff --git a/Godeps/_workspace/src/github.com/spf13/viper/.gitignore b/Godeps/_workspace/src/github.com/spf13/viper/.gitignore new file mode 100644 index 00000000..83656241 --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/viper/.gitignore @@ -0,0 +1,23 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test diff --git a/Godeps/_workspace/src/github.com/spf13/viper/.travis.yml b/Godeps/_workspace/src/github.com/spf13/viper/.travis.yml new file mode 100644 index 00000000..a578cbf6 --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/viper/.travis.yml @@ -0,0 +1,9 @@ +language: go +go: + - 1.2 + - 1.3 + - release + - tip + +script: + - go test -v ./... diff --git a/Godeps/_workspace/src/github.com/spf13/viper/LICENSE b/Godeps/_workspace/src/github.com/spf13/viper/LICENSE new file mode 100644 index 00000000..4527efb9 --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/viper/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Steve Francia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/spf13/viper/README.md b/Godeps/_workspace/src/github.com/spf13/viper/README.md new file mode 100644 index 00000000..16d017ba --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/viper/README.md @@ -0,0 +1,440 @@ +viper [![Build Status](https://travis-ci.org/spf13/viper.svg)](https://travis-ci.org/spf13/viper) +===== + +[![Join the chat at https://gitter.im/spf13/viper](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +Go configuration with fangs + +## What is Viper? + +Viper is a complete configuration solution for go applications. It has +been designed to work within an application to handle all types of +configuration. It supports + +* setting defaults +* reading from json, toml and yaml config files +* reading from environment variables +* reading from remote config systems (Etcd or Consul), watching changes +* reading from command line flags +* reading from buffer +* setting explicit values + +It can be thought of as a registry for all of your applications +configuration needs. + +## Why Viper? + +When building a modern application, you don’t want to have to worry about +configuration file formats; you want to focus on building awesome software. +Viper is here to help with that. + +Viper does the following for you: + +1. Find, load and marshal a configuration file in JSON, TOML or YAML. +2. Provide a mechanism to set default values for your different + configuration options. +3. Provide a mechanism to set override values for options specified + through command line flags. +4. Provide an alias system to easily rename parameters without breaking + existing code. +5. Make it easy to tell the difference between when a user has provided + a command line or config file which is the same as the default. + +Viper uses the following precedence order. Each item takes precedence +over the item below it: + + * explicit call to Set + * flag + * env + * config + * key/value store + * default + +Viper configuration keys are case insensitive. + +## Putting Values into Viper + +### Establishing Defaults + +A good configuration system will support default values. A default value +is not required for a key, but can establish a default to be used in the +event that the key hasn’t be set via config file, environment variable, +remote configuration or flag. + +Examples: + + viper.SetDefault("ContentDir", "content") + viper.SetDefault("LayoutDir", "layouts") + viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"}) + +### Reading Config Files + +If you want to support a config file, Viper requires a minimal +configuration so it knows where to look for the config file. Viper +supports json, toml and yaml files. Viper can search multiple paths, but +currently a single viper only supports a single config file. + + viper.SetConfigName("config") // name of config file (without extension) + viper.AddConfigPath("/etc/appname/") // path to look for the config file in + viper.AddConfigPath("$HOME/.appname") // call multiple times to add many search paths + err := viper.ReadInConfig() // Find and read the config file + if err != nil { // Handle errors reading the config file + panic(fmt.Errorf("Fatal error config file: %s \n", err)) + } + +### Reading Config from io.Reader + +Viper predefined many configuration sources, such as files, environment variables, flags and +remote K/V store. But you are not bound to them. You can also implement your own way to +require configuration and feed it to viper. + +````go +viper.SetConfigType("yaml") // or viper.SetConfigType("YAML") + +// any approach to require this configuration into your program. +var yamlExample = []byte(` +Hacker: true +name: steve +hobbies: +- skateboarding +- snowboarding +- go +clothing: + jacket: leather + trousers: denim +age: 35 +eyes : brown +beard: true +`) + +viper.ReadConfig(bytes.NewBuffer(yamlExample)) + +viper.Get("name") // this would be "steve" +```` + +### Setting Overrides + +These could be from a command line flag, or from your own application logic. + + viper.Set("Verbose", true) + viper.Set("LogFile", LogFile) + +### Registering and Using Aliases + +Aliases permit a single value to be referenced by multiple keys + + viper.RegisterAlias("loud", "Verbose") + + viper.Set("verbose", true) // same result as next line + viper.Set("loud", true) // same result as prior line + + viper.GetBool("loud") // true + viper.GetBool("verbose") // true + +### Working with Environment Variables + +Viper has full support for environment variables. This enables 12 factor +applications out of the box. There are four methods that exist to aid +with working with ENV: + + * AutomaticEnv() + * BindEnv(string...) : error + * SetEnvPrefix(string) + * SetEnvReplacer(string...) *strings.Replacer + +_When working with ENV variables, it’s important to recognize that Viper +treats ENV variables as case sensitive._ + +Viper provides a mechanism to try to ensure that ENV variables are +unique. By using SetEnvPrefix, you can tell Viper to use add a prefix +while reading from the environment variables. Both BindEnv and +AutomaticEnv will use this prefix. + +BindEnv takes one or two parameters. The first parameter is the key +name, the second is the name of the environment variable. The name of +the environment variable is case sensitive. If the ENV variable name is +not provided, then Viper will automatically assume that the key name +matches the ENV variable name but the ENV variable is IN ALL CAPS. When +you explicitly provide the ENV variable name, it **does not** +automatically add the prefix. + +One important thing to recognize when working with ENV variables is that +the value will be read each time it is accessed. It does not fix the +value when the BindEnv is called. + +AutomaticEnv is a powerful helper especially when combined with +SetEnvPrefix. When called, Viper will check for an environment variable +any time a viper.Get request is made. It will apply the following rules. +It will check for a environment variable with a name matching the key +uppercased and prefixed with the EnvPrefix if set. + +SetEnvReplacer allows you to use a `strings.Replacer` object to rewrite Env keys +to an extent. This is useful if you want to use `-` or something in your Get() +calls, but want your environmental variables to use `_` delimiters. An example +of using it can be found in `viper_test.go`. + +#### Env example + + SetEnvPrefix("spf") // will be uppercased automatically + BindEnv("id") + + os.Setenv("SPF_ID", "13") // typically done outside of the app + + id := Get("id") // 13 + + +### Working with Flags + +Viper has the ability to bind to flags. Specifically, Viper supports +Pflags as used in the [Cobra](https://github.com/spf13/cobra) library. + +Like BindEnv, the value is not set when the binding method is called, but +when it is accessed. This means you can bind as early as you want, even +in an init() function. + +The BindPFlag() method provides this functionality. + +Example: + + serverCmd.Flags().Int("port", 1138, "Port to run Application server on") + viper.BindPFlag("port", serverCmd.Flags().Lookup("port")) + + +### Remote Key/Value Store Support +Viper will read a config string (as JSON, TOML, or YAML) retrieved from a +path in a Key/Value store such as Etcd or Consul. These values take precedence +over default values, but are overriden by configuration values retrieved from disk, +flags, or environment variables. + +Viper uses [crypt](https://github.com/xordataexchange/crypt) to retrieve configuration +from the K/V store, which means that you can store your configuration values +encrypted and have them automatically decrypted if you have the correct +gpg keyring. Encryption is optional. + +You can use remote configuration in conjunction with local configuration, or +independently of it. + +`crypt` has a command-line helper that you can use to put configurations +in your K/V store. `crypt` defaults to etcd on http://127.0.0.1:4001. + + go get github.com/xordataexchange/crypt/bin/crypt + crypt set -plaintext /config/hugo.json /Users/hugo/settings/config.json + +Confirm that your value was set: + + crypt get -plaintext /config/hugo.json + +See the `crypt` documentation for examples of how to set encrypted values, or how +to use Consul. + +### Remote Key/Value Store Example - Unencrypted + + viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001","/config/hugo.json") + viper.SetConfigType("json") // because there is no file extension in a stream of bytes + err := viper.ReadRemoteConfig() + +### Remote Key/Value Store Example - Encrypted + + viper.AddSecureRemoteProvider("etcd","http://127.0.0.1:4001","/config/hugo.json","/etc/secrets/mykeyring.gpg") + viper.SetConfigType("json") // because there is no file extension in a stream of bytes + err := viper.ReadRemoteConfig() + +### Watching Changes in Etcd - Unencrypted + + // alternatively, you can create a new viper instance. + var runtime_viper = viper.New() + + runtime_viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001", "/config/hugo.yml") + runtime_viper.SetConfigType("yaml") // because there is no file extension in a stream of bytes + + // read from remote config the first time. + err := runtime_viper.ReadRemoteConfig() + + // marshal config + runtime_viper.Marshal(&runtime_conf) + + // open a goroutine to wath remote changes forever + go func(){ + for { + time.Sleep(time.Second * 5) // delay after each request + + // currenlty, only tested with etcd support + err := runtime_viper.WatchRemoteConfig() + if err != nil { + log.Errorf("unable to read remote config: %v", err) + continue + } + + // marshal new config into our runtime config struct. you can also use channel + // to implement a signal to notify the system of the changes + runtime_viper.Marshal(&runtime_conf) + } + }() + + +## Getting Values From Viper + +In Viper, there are a few ways to get a value depending on what type of value you want to retrieved. +The following functions and methods exist: + + * Get(key string) : interface{} + * GetBool(key string) : bool + * GetFloat64(key string) : float64 + * GetInt(key string) : int + * GetString(key string) : string + * GetStringMap(key string) : map[string]interface{} + * GetStringMapString(key string) : map[string]string + * GetStringSlice(key string) : []string + * GetTime(key string) : time.Time + * GetDuration(key string) : time.Duration + * IsSet(key string) : bool + +One important thing to recognize is that each Get function will return +its zero value if it’s not found. To check if a given key exists, the IsSet() +method has been provided. + +Example: + + viper.GetString("logfile") // case-insensitive Setting & Getting + if viper.GetBool("verbose") { + fmt.Println("verbose enabled") + } + +### Accessing nested keys + +The accessor methods also accept formatted paths to deeply nested keys. +For example, if the following JSON file is loaded: + +``` +{ + "host": { + "address": "localhost", + "port": 5799 + }, + "datastore": { + "metric": { + "host": "127.0.0.1", + "port": 3099 + }, + "warehouse": { + "host": "198.0.0.1", + "port": 2112 + } + } +} + +``` + +Viper can access a nested field by passing a `.` delimited path of keys: +``` +GetString("datastore.metric.host") // (returns "127.0.0.1") +``` + +This obeys the precendense rules established above; the search for the root key +(in this examole, `datastore`) will cascade through the remaining configuration registries +until found. The search for the subkeys (`metric` and `host`), however, will not. + +For example, if the `metric` key was not defined in the configuration loaded +from file, but was defined in the defaults, Viper would return the zero value. + +On the other hand, if the primary key was not defined, Viper would go through the +remaining registries looking for it. + +Lastly, if there exists a key that matches the delimited key path, its value will +be returned instead. E.g. + +``` +{ + "datastore.metric.host": "0.0.0.0", + "host": { + "address": "localhost", + "port": 5799 + }, + "datastore": { + "metric": { + "host": "127.0.0.1", + "port": 3099 + }, + "warehouse": { + "host": "198.0.0.1", + "port": 2112 + } + } +} + +GetString("datastore.metric.host") //returns "0.0.0.0" +``` + +### Marshaling + +You also have the option of Marshaling all or a specific value to a struct, map, etc. + +There are two methods to do this: + + * Marshal(rawVal interface{}) : error + * MarshalKey(key string, rawVal interface{}) : error + +Example: + + type config struct { + Port int + Name string + } + + var C config + + err := Marshal(&C) + if err != nil { + t.Fatalf("unable to decode into struct, %v", err) + } + + +## Viper or Vipers? + +Viper comes ready to use out of the box. There is no configuration or +initialization needed to begin using Viper. Since most applications will +want to use a single central repository for their configuration, the +viper package provides this. It is similar to a singleton. + +In all of the examples above, they demonstrate using viper in its +singleton style approach. + +### Working with multiple vipers + +You can also create many different vipers for use in your application. +Each will have it’s own unique set of configurations and values. Each +can read from a different config file, key value store, etc. All of the +functions that viper package supports are mirrored as methods on a viper. + +Example: + + x := viper.New() + y := viper.New() + + x.SetDefault("ContentDir", "content") + y.SetDefault("ContentDir", "foobar") + + ... + +When working with multiple vipers, it is up to the user to keep track of +the different vipers. + +## Q & A + +Q: Why not INI files? + +A: Ini files are pretty awful. There’s no standard format, and they are hard to +validate. Viper is designed to work with JSON, TOML or YAML files. If someone +really wants to add this feature, I’d be happy to merge it. It’s easy to +specify which formats your application will permit. + +Q: Why is it called “Viper”? + +A: Viper is designed to be a [companion](http://en.wikipedia.org/wiki/Viper_(G.I._Joe)) to +[Cobra](https://github.com/spf13/cobra). While both can operate completely +independently, together they make a powerful pair to handle much of your +application foundation needs. + +Q: Why is it called “Cobra”? + +A: Is there a better name for a [commander](http://en.wikipedia.org/wiki/Cobra_Commander)? diff --git a/Godeps/_workspace/src/github.com/spf13/viper/util.go b/Godeps/_workspace/src/github.com/spf13/viper/util.go new file mode 100644 index 00000000..f602a5a4 --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/viper/util.go @@ -0,0 +1,198 @@ +// Copyright © 2014 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// Viper is a application configuration system. +// It believes that applications can be configured a variety of ways +// via flags, ENVIRONMENT variables, configuration files retrieved +// from the file system, or a remote key/value store. + +package viper + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "os" + "path/filepath" + "runtime" + "strings" + "unicode" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/BurntSushi/toml" + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/magiconair/properties" + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/spf13/cast" + jww "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/spf13/jwalterweatherman" + "github.com/khlieng/name_pending/Godeps/_workspace/src/gopkg.in/yaml.v2" +) + +func insensitiviseMap(m map[string]interface{}) { + for key, val := range m { + lower := strings.ToLower(key) + if key != lower { + delete(m, key) + m[lower] = val + } + } +} + +func absPathify(inPath string) string { + jww.INFO.Println("Trying to resolve absolute path to", inPath) + + if strings.HasPrefix(inPath, "$HOME") { + inPath = userHomeDir() + inPath[5:] + } + + if strings.HasPrefix(inPath, "$") { + end := strings.Index(inPath, string(os.PathSeparator)) + inPath = os.Getenv(inPath[1:end]) + inPath[end:] + } + + if filepath.IsAbs(inPath) { + return filepath.Clean(inPath) + } + + p, err := filepath.Abs(inPath) + if err == nil { + return filepath.Clean(p) + } else { + jww.ERROR.Println("Couldn't discover absolute path") + jww.ERROR.Println(err) + } + return "" +} + +// Check if File / Directory Exists +func exists(path string) (bool, error) { + _, err := os.Stat(path) + if err == nil { + return true, nil + } + if os.IsNotExist(err) { + return false, nil + } + return false, err +} + +func stringInSlice(a string, list []string) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +} + +func userHomeDir() string { + if runtime.GOOS == "windows" { + home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") + if home == "" { + home = os.Getenv("USERPROFILE") + } + return home + } + return os.Getenv("HOME") +} + +func findCWD() (string, error) { + serverFile, err := filepath.Abs(os.Args[0]) + + if err != nil { + return "", fmt.Errorf("Can't get absolute path for executable: %v", err) + } + + path := filepath.Dir(serverFile) + realFile, err := filepath.EvalSymlinks(serverFile) + + if err != nil { + if _, err = os.Stat(serverFile + ".exe"); err == nil { + realFile = filepath.Clean(serverFile + ".exe") + } + } + + if err == nil && realFile != serverFile { + path = filepath.Dir(realFile) + } + + return path, nil +} + +func marshallConfigReader(in io.Reader, c map[string]interface{}, configType string) { + buf := new(bytes.Buffer) + buf.ReadFrom(in) + + switch strings.ToLower(configType) { + case "yaml", "yml": + if err := yaml.Unmarshal(buf.Bytes(), &c); err != nil { + jww.ERROR.Fatalf("Error parsing config: %s", err) + } + + case "json": + if err := json.Unmarshal(buf.Bytes(), &c); err != nil { + jww.ERROR.Fatalf("Error parsing config: %s", err) + } + + case "toml": + if _, err := toml.Decode(buf.String(), &c); err != nil { + jww.ERROR.Fatalf("Error parsing config: %s", err) + } + + case "properties", "props", "prop": + var p *properties.Properties + var err error + if p, err = properties.Load(buf.Bytes(), properties.UTF8); err != nil { + jww.ERROR.Fatalf("Error parsing config: %s", err) + } + for _, key := range p.Keys() { + value, _ := p.Get(key) + c[key] = value + } + } + + insensitiviseMap(c) +} + +func safeMul(a, b uint) uint { + c := a * b + if a > 1 && b > 1 && c/b != a { + return 0 + } + return c +} + +// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes +func parseSizeInBytes(sizeStr string) uint { + sizeStr = strings.TrimSpace(sizeStr) + lastChar := len(sizeStr) - 1 + multiplier := uint(1) + + if lastChar > 0 { + if sizeStr[lastChar] == 'b' || sizeStr[lastChar] == 'B' { + if lastChar > 1 { + switch unicode.ToLower(rune(sizeStr[lastChar-1])) { + case 'k': + multiplier = 1 << 10 + sizeStr = strings.TrimSpace(sizeStr[:lastChar-1]) + case 'm': + multiplier = 1 << 20 + sizeStr = strings.TrimSpace(sizeStr[:lastChar-1]) + case 'g': + multiplier = 1 << 30 + sizeStr = strings.TrimSpace(sizeStr[:lastChar-1]) + default: + multiplier = 1 + sizeStr = strings.TrimSpace(sizeStr[:lastChar]) + } + } + } + } + + size := cast.ToInt(sizeStr) + if size < 0 { + size = 0 + } + + return safeMul(uint(size), multiplier) +} diff --git a/Godeps/_workspace/src/github.com/spf13/viper/viper.go b/Godeps/_workspace/src/github.com/spf13/viper/viper.go new file mode 100644 index 00000000..922139bf --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/viper/viper.go @@ -0,0 +1,997 @@ +// Copyright © 2014 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// Viper is a application configuration system. +// It believes that applications can be configured a variety of ways +// via flags, ENVIRONMENT variables, configuration files retrieved +// from the file system, or a remote key/value store. + +// Each item takes precedence over the item below it: + +// overrides +// flag +// env +// config +// key/value store +// default + +package viper + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "reflect" + "strings" + "time" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/kr/pretty" + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/mitchellh/mapstructure" + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/spf13/cast" + jww "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/spf13/jwalterweatherman" + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/spf13/pflag" + crypt "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/xordataexchange/crypt/config" +) + +var v *Viper + +func init() { + v = New() +} + +// Denotes encountering an unsupported +// configuration filetype. +type UnsupportedConfigError string + +// Returns the formatted configuration error. +func (str UnsupportedConfigError) Error() string { + return fmt.Sprintf("Unsupported Config Type %q", string(str)) +} + +// Denotes encountering an unsupported remote +// provider. Currently only Etcd and Consul are +// supported. +type UnsupportedRemoteProviderError string + +// Returns the formatted remote provider error. +func (str UnsupportedRemoteProviderError) Error() string { + return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str)) +} + +// Denotes encountering an error while trying to +// pull the configuration from the remote provider. +type RemoteConfigError string + +// Returns the formatted remote provider error +func (rce RemoteConfigError) Error() string { + return fmt.Sprintf("Remote Configurations Error: %s", string(rce)) +} + +// Viper is a prioritized configuration registry. It +// maintains a set of configuration sources, fetches +// values to populate those, and provides them according +// to the source's priority. +// The priority of the sources is the following: +// 1. overrides +// 2. flags +// 3. env. variables +// 4. config file +// 5. key/value store +// 6. defaults +// +// For example, if values from the following sources were loaded: +// +// Defaults : { +// "secret": "", +// "user": "default", +// "endpoint": "https://localhost" +// } +// Config : { +// "user": "root" +// "secret": "defaultsecret" +// } +// Env : { +// "secret": "somesecretkey" +// } +// +// The resulting config will have the following values: +// +// { +// "secret": "somesecretkey", +// "user": "root", +// "endpoint": "https://localhost" +// } +type Viper struct { + // Delimiter that separates a list of keys + // used to access a nested value in one go + keyDelim string + + // A set of paths to look for the config file in + configPaths []string + + // A set of remote providers to search for the configuration + remoteProviders []*remoteProvider + + // Name of file to look for inside the path + configName string + configFile string + configType string + envPrefix string + + automaticEnvApplied bool + envKeyReplacer *strings.Replacer + + config map[string]interface{} + override map[string]interface{} + defaults map[string]interface{} + kvstore map[string]interface{} + pflags map[string]*pflag.Flag + env map[string]string + aliases map[string]string +} + +// Returns an initialized Viper instance. +func New() *Viper { + v := new(Viper) + v.keyDelim = "." + v.configName = "config" + v.config = make(map[string]interface{}) + v.override = make(map[string]interface{}) + v.defaults = make(map[string]interface{}) + v.kvstore = make(map[string]interface{}) + v.pflags = make(map[string]*pflag.Flag) + v.env = make(map[string]string) + v.aliases = make(map[string]string) + + return v +} + +// Intended for testing, will reset all to default settings. +// In the public interface for the viper package so applications +// can use it in their testing as well. +func Reset() { + v = New() + SupportedExts = []string{"json", "toml", "yaml", "yml"} + SupportedRemoteProviders = []string{"etcd", "consul"} +} + +// remoteProvider stores the configuration necessary +// to connect to a remote key/value store. +// Optional secretKeyring to unencrypt encrypted values +// can be provided. +type remoteProvider struct { + provider string + endpoint string + path string + secretKeyring string +} + +// Universally supported extensions. +var SupportedExts []string = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop"} + +// Universally supported remote providers. +var SupportedRemoteProviders []string = []string{"etcd", "consul"} + +// Explicitly define the path, name and extension of the config file +// Viper will use this and not check any of the config paths +func SetConfigFile(in string) { v.SetConfigFile(in) } +func (v *Viper) SetConfigFile(in string) { + if in != "" { + v.configFile = in + } +} + +// Define a prefix that ENVIRONMENT variables will use. +// E.g. if your prefix is "spf", the env registry +// will look for env. variables that start with "SPF_" +func SetEnvPrefix(in string) { v.SetEnvPrefix(in) } +func (v *Viper) SetEnvPrefix(in string) { + if in != "" { + v.envPrefix = in + } +} + +func (v *Viper) mergeWithEnvPrefix(in string) string { + if v.envPrefix != "" { + return strings.ToUpper(v.envPrefix + "_" + in) + } + + return strings.ToUpper(in) +} + +// TODO: should getEnv logic be moved into find(). Can generalize the use of +// rewriting keys many things, Ex: Get('someKey') -> some_key +// (cammel case to snake case for JSON keys perhaps) + +// getEnv s a wrapper around os.Getenv which replaces characters in the original +// key. This allows env vars which have different keys then the config object +// keys +func (v *Viper) getEnv(key string) string { + if v.envKeyReplacer != nil { + key = v.envKeyReplacer.Replace(key) + } + return os.Getenv(key) +} + +// Return the file used to populate the config registry +func ConfigFileUsed() string { return v.ConfigFileUsed() } +func (v *Viper) ConfigFileUsed() string { return v.configFile } + +// Add a path for Viper to search for the config file in. +// Can be called multiple times to define multiple search paths. +func AddConfigPath(in string) { v.AddConfigPath(in) } +func (v *Viper) AddConfigPath(in string) { + if in != "" { + absin := absPathify(in) + jww.INFO.Println("adding", absin, "to paths to search") + if !stringInSlice(absin, v.configPaths) { + v.configPaths = append(v.configPaths, absin) + } + } +} + +// AddRemoteProvider adds a remote configuration source. +// Remote Providers are searched in the order they are added. +// provider is a string value, "etcd" or "consul" are currently supported. +// endpoint is the url. etcd requires http://ip:port consul requires ip:port +// path is the path in the k/v store to retrieve configuration +// To retrieve a config file called myapp.json from /configs/myapp.json +// you should set path to /configs and set config name (SetConfigName()) to +// "myapp" +func AddRemoteProvider(provider, endpoint, path string) error { + return v.AddRemoteProvider(provider, endpoint, path) +} +func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error { + if !stringInSlice(provider, SupportedRemoteProviders) { + return UnsupportedRemoteProviderError(provider) + } + if provider != "" && endpoint != "" { + jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint) + rp := &remoteProvider{ + endpoint: endpoint, + provider: provider, + path: path, + } + if !v.providerPathExists(rp) { + v.remoteProviders = append(v.remoteProviders, rp) + } + } + return nil +} + +// AddSecureRemoteProvider adds a remote configuration source. +// Secure Remote Providers are searched in the order they are added. +// provider is a string value, "etcd" or "consul" are currently supported. +// endpoint is the url. etcd requires http://ip:port consul requires ip:port +// secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg +// path is the path in the k/v store to retrieve configuration +// To retrieve a config file called myapp.json from /configs/myapp.json +// you should set path to /configs and set config name (SetConfigName()) to +// "myapp" +// Secure Remote Providers are implemented with github.com/xordataexchange/crypt +func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { + return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring) +} + +func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { + if !stringInSlice(provider, SupportedRemoteProviders) { + return UnsupportedRemoteProviderError(provider) + } + if provider != "" && endpoint != "" { + jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint) + rp := &remoteProvider{ + endpoint: endpoint, + provider: provider, + path: path, + } + if !v.providerPathExists(rp) { + v.remoteProviders = append(v.remoteProviders, rp) + } + } + return nil +} + +func (v *Viper) providerPathExists(p *remoteProvider) bool { + for _, y := range v.remoteProviders { + if reflect.DeepEqual(y, p) { + return true + } + } + return false +} + +func (v *Viper) searchMap(source map[string]interface{}, path []string) interface{} { + + if len(path) == 0 { + return source + } + + if next, ok := source[path[0]]; ok { + switch next.(type) { + case map[string]interface{}: + // Type assertion is safe here since it is only reached + // if the type of `next` is the same as the type being asserted + return v.searchMap(next.(map[string]interface{}), path[1:]) + default: + return next + } + } else { + return nil + } +} + +// Viper is essentially repository for configurations +// Get can retrieve any value given the key to use +// Get has the behavior of returning the value associated with the first +// place from where it is set. Viper will check in the following order: +// override, flag, env, config file, key/value store, default +// +// Get returns an interface. For a specific value use one of the Get____ methods. +func Get(key string) interface{} { return v.Get(key) } +func (v *Viper) Get(key string) interface{} { + path := strings.Split(key, v.keyDelim) + + val := v.find(strings.ToLower(key)) + + if val == nil { + source := v.find(path[0]) + if source == nil { + return nil + } + + if reflect.TypeOf(source).Kind() == reflect.Map { + val = v.searchMap(cast.ToStringMap(source), path[1:]) + } + } + + switch val.(type) { + case bool: + return cast.ToBool(val) + case string: + return cast.ToString(val) + case int64, int32, int16, int8, int: + return cast.ToInt(val) + case float64, float32: + return cast.ToFloat64(val) + case time.Time: + return cast.ToTime(val) + case time.Duration: + return cast.ToDuration(val) + case []string: + return val + } + return val +} + +// Returns the value associated with the key as a string +func GetString(key string) string { return v.GetString(key) } +func (v *Viper) GetString(key string) string { + return cast.ToString(v.Get(key)) +} + +// Returns the value associated with the key asa boolean +func GetBool(key string) bool { return v.GetBool(key) } +func (v *Viper) GetBool(key string) bool { + return cast.ToBool(v.Get(key)) +} + +// Returns the value associated with the key as an integer +func GetInt(key string) int { return v.GetInt(key) } +func (v *Viper) GetInt(key string) int { + return cast.ToInt(v.Get(key)) +} + +// Returns the value associated with the key as a float64 +func GetFloat64(key string) float64 { return v.GetFloat64(key) } +func (v *Viper) GetFloat64(key string) float64 { + return cast.ToFloat64(v.Get(key)) +} + +// Returns the value associated with the key as time +func GetTime(key string) time.Time { return v.GetTime(key) } +func (v *Viper) GetTime(key string) time.Time { + return cast.ToTime(v.Get(key)) +} + +// Returns the value associated with the key as a duration +func GetDuration(key string) time.Duration { return v.GetDuration(key) } +func (v *Viper) GetDuration(key string) time.Duration { + return cast.ToDuration(v.Get(key)) +} + +// Returns the value associated with the key as a slice of strings +func GetStringSlice(key string) []string { return v.GetStringSlice(key) } +func (v *Viper) GetStringSlice(key string) []string { + return cast.ToStringSlice(v.Get(key)) +} + +// Returns the value associated with the key as a map of interfaces +func GetStringMap(key string) map[string]interface{} { return v.GetStringMap(key) } +func (v *Viper) GetStringMap(key string) map[string]interface{} { + return cast.ToStringMap(v.Get(key)) +} + +// Returns the value associated with the key as a map of strings +func GetStringMapString(key string) map[string]string { return v.GetStringMapString(key) } +func (v *Viper) GetStringMapString(key string) map[string]string { + return cast.ToStringMapString(v.Get(key)) +} + +// Returns the size of the value associated with the given key +// in bytes. +func GetSizeInBytes(key string) uint { return v.GetSizeInBytes(key) } +func (v *Viper) GetSizeInBytes(key string) uint { + sizeStr := cast.ToString(v.Get(key)) + return parseSizeInBytes(sizeStr) +} + +// Takes a single key and marshals it into a Struct +func MarshalKey(key string, rawVal interface{}) error { return v.MarshalKey(key, rawVal) } +func (v *Viper) MarshalKey(key string, rawVal interface{}) error { + return mapstructure.Decode(v.Get(key), rawVal) +} + +// Marshals the config into a Struct. Make sure that the tags +// on the fields of the structure are properly set. +func Marshal(rawVal interface{}) error { return v.Marshal(rawVal) } +func (v *Viper) Marshal(rawVal interface{}) error { + err := mapstructure.WeakDecode(v.AllSettings(), rawVal) + + if err != nil { + return err + } + + v.insensitiviseMaps() + + return nil +} + +// Bind a full flag set to the configuration, using each flag's long +// name as the config key. +func BindPFlags(flags *pflag.FlagSet) (err error) { return v.BindPFlags(flags) } +func (v *Viper) BindPFlags(flags *pflag.FlagSet) (err error) { + flags.VisitAll(func(flag *pflag.Flag) { + if err != nil { + // an error has been encountered in one of the previous flags + return + } + + err = v.BindPFlag(flag.Name, flag) + switch flag.Value.Type() { + case "int", "int8", "int16", "int32", "int64": + v.SetDefault(flag.Name, cast.ToInt(flag.Value.String())) + case "bool": + v.SetDefault(flag.Name, cast.ToBool(flag.Value.String())) + default: + v.SetDefault(flag.Name, flag.Value.String()) + } + }) + return +} + +// Bind a specific key to a flag (as used by cobra) +// Example(where serverCmd is a Cobra instance): +// +// serverCmd.Flags().Int("port", 1138, "Port to run Application server on") +// Viper.BindPFlag("port", serverCmd.Flags().Lookup("port")) +// +func BindPFlag(key string, flag *pflag.Flag) (err error) { return v.BindPFlag(key, flag) } +func (v *Viper) BindPFlag(key string, flag *pflag.Flag) (err error) { + if flag == nil { + return fmt.Errorf("flag for %q is nil", key) + } + v.pflags[strings.ToLower(key)] = flag + + switch flag.Value.Type() { + case "int", "int8", "int16", "int32", "int64": + SetDefault(key, cast.ToInt(flag.Value.String())) + case "bool": + SetDefault(key, cast.ToBool(flag.Value.String())) + default: + SetDefault(key, flag.Value.String()) + } + return nil +} + +// Binds a Viper key to a ENV variable +// ENV variables are case sensitive +// If only a key is provided, it will use the env key matching the key, uppercased. +// EnvPrefix will be used when set when env name is not provided. +func BindEnv(input ...string) (err error) { return v.BindEnv(input...) } +func (v *Viper) BindEnv(input ...string) (err error) { + var key, envkey string + if len(input) == 0 { + return fmt.Errorf("BindEnv missing key to bind to") + } + + key = strings.ToLower(input[0]) + + if len(input) == 1 { + envkey = v.mergeWithEnvPrefix(key) + } else { + envkey = input[1] + } + + v.env[key] = envkey + + return nil +} + +// Given a key, find the value +// Viper will check in the following order: +// flag, env, config file, key/value store, default +// Viper will check to see if an alias exists first +func (v *Viper) find(key string) interface{} { + var val interface{} + var exists bool + + // if the requested key is an alias, then return the proper key + key = v.realKey(key) + + // PFlag Override first + flag, exists := v.pflags[key] + if exists { + if flag.Changed { + jww.TRACE.Println(key, "found in override (via pflag):", val) + return flag.Value.String() + } + } + + val, exists = v.override[key] + if exists { + jww.TRACE.Println(key, "found in override:", val) + return val + } + + if v.automaticEnvApplied { + // even if it hasn't been registered, if automaticEnv is used, + // check any Get request + if val = v.getEnv(v.mergeWithEnvPrefix(key)); val != "" { + jww.TRACE.Println(key, "found in environment with val:", val) + return val + } + } + + envkey, exists := v.env[key] + if exists { + jww.TRACE.Println(key, "registered as env var", envkey) + if val = v.getEnv(envkey); val != "" { + jww.TRACE.Println(envkey, "found in environment with val:", val) + return val + } else { + jww.TRACE.Println(envkey, "env value unset:") + } + } + + val, exists = v.config[key] + if exists { + jww.TRACE.Println(key, "found in config:", val) + return val + } + + val, exists = v.kvstore[key] + if exists { + jww.TRACE.Println(key, "found in key/value store:", val) + return val + } + + val, exists = v.defaults[key] + if exists { + jww.TRACE.Println(key, "found in defaults:", val) + return val + } + + return nil +} + +// Check to see if the key has been set in any of the data locations +func IsSet(key string) bool { return v.IsSet(key) } +func (v *Viper) IsSet(key string) bool { + t := v.Get(key) + return t != nil +} + +// Have Viper check ENV variables for all +// keys set in config, default & flags +func AutomaticEnv() { v.AutomaticEnv() } +func (v *Viper) AutomaticEnv() { + v.automaticEnvApplied = true +} + +// SetEnvKeyReplacer sets the strings.Replacer on the viper object +// Useful for mapping an environmental variable to a key that does +// not match it. +func SetEnvKeyReplacer(r *strings.Replacer) { v.SetEnvKeyReplacer(r) } +func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) { + v.envKeyReplacer = r +} + +// Aliases provide another accessor for the same key. +// This enables one to change a name without breaking the application +func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) } +func (v *Viper) RegisterAlias(alias string, key string) { + v.registerAlias(alias, strings.ToLower(key)) +} + +func (v *Viper) registerAlias(alias string, key string) { + alias = strings.ToLower(alias) + if alias != key && alias != v.realKey(key) { + _, exists := v.aliases[alias] + + if !exists { + // if we alias something that exists in one of the maps to another + // name, we'll never be able to get that value using the original + // name, so move the config value to the new realkey. + if val, ok := v.config[alias]; ok { + delete(v.config, alias) + v.config[key] = val + } + if val, ok := v.kvstore[alias]; ok { + delete(v.kvstore, alias) + v.kvstore[key] = val + } + if val, ok := v.defaults[alias]; ok { + delete(v.defaults, alias) + v.defaults[key] = val + } + if val, ok := v.override[alias]; ok { + delete(v.override, alias) + v.override[key] = val + } + v.aliases[alias] = key + } + } else { + jww.WARN.Println("Creating circular reference alias", alias, key, v.realKey(key)) + } +} + +func (v *Viper) realKey(key string) string { + newkey, exists := v.aliases[key] + if exists { + jww.DEBUG.Println("Alias", key, "to", newkey) + return v.realKey(newkey) + } else { + return key + } +} + +// Check to see if the given key (or an alias) is in the config file +func InConfig(key string) bool { return v.InConfig(key) } +func (v *Viper) InConfig(key string) bool { + // if the requested key is an alias, then return the proper key + key = v.realKey(key) + + _, exists := v.config[key] + return exists +} + +// Set the default value for this key. +// Default only used when no value is provided by the user via flag, config or ENV. +func SetDefault(key string, value interface{}) { v.SetDefault(key, value) } +func (v *Viper) SetDefault(key string, value interface{}) { + // If alias passed in, then set the proper default + key = v.realKey(strings.ToLower(key)) + v.defaults[key] = value +} + +// Sets the value for the key in the override regiser. +// Will be used instead of values obtained via +// flags, config file, ENV, default, or key/value store +func Set(key string, value interface{}) { v.Set(key, value) } +func (v *Viper) Set(key string, value interface{}) { + // If alias passed in, then set the proper override + key = v.realKey(strings.ToLower(key)) + v.override[key] = value +} + +// Viper will discover and load the configuration file from disk +// and key/value stores, searching in one of the defined paths. +func ReadInConfig() error { return v.ReadInConfig() } +func (v *Viper) ReadInConfig() error { + jww.INFO.Println("Attempting to read in config file") + if !stringInSlice(v.getConfigType(), SupportedExts) { + return UnsupportedConfigError(v.getConfigType()) + } + + file, err := ioutil.ReadFile(v.getConfigFile()) + if err != nil { + return err + } + + v.config = make(map[string]interface{}) + + v.marshalReader(bytes.NewReader(file), v.config) + return nil +} + +func ReadConfig(in io.Reader) error { return v.ReadConfig(in) } +func (v *Viper) ReadConfig(in io.Reader) error { + v.config = make(map[string]interface{}) + v.marshalReader(in, v.config) + return nil +} + +// func ReadBufConfig(buf *bytes.Buffer) error { return v.ReadBufConfig(buf) } +// func (v *Viper) ReadBufConfig(buf *bytes.Buffer) error { +// v.config = make(map[string]interface{}) +// v.marshalReader(buf, v.config) +// return nil +// } + +// Attempts to get configuration from a remote source +// and read it in the remote configuration registry. +func ReadRemoteConfig() error { return v.ReadRemoteConfig() } +func (v *Viper) ReadRemoteConfig() error { + err := v.getKeyValueConfig() + if err != nil { + return err + } + return nil +} + +func WatchRemoteConfig() error { return v.WatchRemoteConfig() } +func (v *Viper) WatchRemoteConfig() error { + err := v.watchKeyValueConfig() + if err != nil { + return err + } + return nil +} + +// Marshall a Reader into a map +// Should probably be an unexported function +func marshalReader(in io.Reader, c map[string]interface{}) { v.marshalReader(in, c) } +func (v *Viper) marshalReader(in io.Reader, c map[string]interface{}) { + marshallConfigReader(in, c, v.getConfigType()) +} + +func (v *Viper) insensitiviseMaps() { + insensitiviseMap(v.config) + insensitiviseMap(v.defaults) + insensitiviseMap(v.override) + insensitiviseMap(v.kvstore) +} + +// retrieve the first found remote configuration +func (v *Viper) getKeyValueConfig() error { + for _, rp := range v.remoteProviders { + val, err := v.getRemoteConfig(rp) + if err != nil { + continue + } + v.kvstore = val + return nil + } + return RemoteConfigError("No Files Found") +} + +func (v *Viper) getRemoteConfig(provider *remoteProvider) (map[string]interface{}, error) { + var cm crypt.ConfigManager + var err error + + if provider.secretKeyring != "" { + kr, err := os.Open(provider.secretKeyring) + defer kr.Close() + if err != nil { + return nil, err + } + if provider.provider == "etcd" { + cm, err = crypt.NewEtcdConfigManager([]string{provider.endpoint}, kr) + } else { + cm, err = crypt.NewConsulConfigManager([]string{provider.endpoint}, kr) + } + } else { + if provider.provider == "etcd" { + cm, err = crypt.NewStandardEtcdConfigManager([]string{provider.endpoint}) + } else { + cm, err = crypt.NewStandardConsulConfigManager([]string{provider.endpoint}) + } + } + if err != nil { + return nil, err + } + b, err := cm.Get(provider.path) + if err != nil { + return nil, err + } + reader := bytes.NewReader(b) + v.marshalReader(reader, v.kvstore) + return v.kvstore, err +} + +// retrieve the first found remote configuration +func (v *Viper) watchKeyValueConfig() error { + for _, rp := range v.remoteProviders { + val, err := v.watchRemoteConfig(rp) + if err != nil { + continue + } + v.kvstore = val + return nil + } + return RemoteConfigError("No Files Found") +} + +func (v *Viper) watchRemoteConfig(provider *remoteProvider) (map[string]interface{}, error) { + var cm crypt.ConfigManager + var err error + + if provider.secretKeyring != "" { + kr, err := os.Open(provider.secretKeyring) + defer kr.Close() + if err != nil { + return nil, err + } + if provider.provider == "etcd" { + cm, err = crypt.NewEtcdConfigManager([]string{provider.endpoint}, kr) + } else { + cm, err = crypt.NewConsulConfigManager([]string{provider.endpoint}, kr) + } + } else { + if provider.provider == "etcd" { + cm, err = crypt.NewStandardEtcdConfigManager([]string{provider.endpoint}) + } else { + cm, err = crypt.NewStandardConsulConfigManager([]string{provider.endpoint}) + } + } + if err != nil { + return nil, err + } + resp := <-cm.Watch(provider.path, nil) + // b, err := cm.Watch(provider.path, nil) + err = resp.Error + if err != nil { + return nil, err + } + + reader := bytes.NewReader(resp.Value) + v.marshalReader(reader, v.kvstore) + return v.kvstore, err +} + +// Return all keys regardless where they are set +func AllKeys() []string { return v.AllKeys() } +func (v *Viper) AllKeys() []string { + m := map[string]struct{}{} + + for key, _ := range v.defaults { + m[key] = struct{}{} + } + + for key, _ := range v.config { + m[key] = struct{}{} + } + + for key, _ := range v.kvstore { + m[key] = struct{}{} + } + + for key, _ := range v.override { + m[key] = struct{}{} + } + + a := []string{} + for x, _ := range m { + a = append(a, x) + } + + return a +} + +// Return all settings as a map[string]interface{} +func AllSettings() map[string]interface{} { return v.AllSettings() } +func (v *Viper) AllSettings() map[string]interface{} { + m := map[string]interface{}{} + for _, x := range v.AllKeys() { + m[x] = v.Get(x) + } + + return m +} + +// Name for the config file. +// Does not include extension. +func SetConfigName(in string) { v.SetConfigName(in) } +func (v *Viper) SetConfigName(in string) { + if in != "" { + v.configName = in + } +} + +// Sets the type of the configuration returned by the +// remote source, e.g. "json". +func SetConfigType(in string) { v.SetConfigType(in) } +func (v *Viper) SetConfigType(in string) { + if in != "" { + v.configType = in + } +} + +func (v *Viper) getConfigType() string { + if v.configType != "" { + return v.configType + } + + cf := v.getConfigFile() + ext := filepath.Ext(cf) + + if len(ext) > 1 { + return ext[1:] + } else { + return "" + } +} + +func (v *Viper) getConfigFile() string { + // if explicitly set, then use it + if v.configFile != "" { + return v.configFile + } + + cf, err := v.findConfigFile() + if err != nil { + return "" + } + + v.configFile = cf + return v.getConfigFile() +} + +func (v *Viper) searchInPath(in string) (filename string) { + jww.DEBUG.Println("Searching for config in ", in) + for _, ext := range SupportedExts { + jww.DEBUG.Println("Checking for", filepath.Join(in, v.configName+"."+ext)) + if b, _ := exists(filepath.Join(in, v.configName+"."+ext)); b { + jww.DEBUG.Println("Found: ", filepath.Join(in, v.configName+"."+ext)) + return filepath.Join(in, v.configName+"."+ext) + } + } + + return "" +} + +// search all configPaths for any config file. +// Returns the first path that exists (and is a config file) +func (v *Viper) findConfigFile() (string, error) { + jww.INFO.Println("Searching for config in ", v.configPaths) + + for _, cp := range v.configPaths { + file := v.searchInPath(cp) + if file != "" { + return file, nil + } + } + + // try the current working directory + wd, _ := os.Getwd() + file := v.searchInPath(wd) + if file != "" { + return file, nil + } + return "", fmt.Errorf("config file not found in: %s", v.configPaths) +} + +// Prints all configuration registries for debugging +// purposes. +func Debug() { v.Debug() } +func (v *Viper) Debug() { + fmt.Println("Aliases:") + pretty.Println(v.aliases) + fmt.Println("Override:") + pretty.Println(v.override) + fmt.Println("PFlags") + pretty.Println(v.pflags) + fmt.Println("Env:") + pretty.Println(v.env) + fmt.Println("Key/Value Store:") + pretty.Println(v.kvstore) + fmt.Println("Config:") + pretty.Println(v.config) + fmt.Println("Defaults:") + pretty.Println(v.defaults) +} diff --git a/Godeps/_workspace/src/github.com/spf13/viper/viper_test.go b/Godeps/_workspace/src/github.com/spf13/viper/viper_test.go new file mode 100644 index 00000000..0900a426 --- /dev/null +++ b/Godeps/_workspace/src/github.com/spf13/viper/viper_test.go @@ -0,0 +1,553 @@ +// Copyright © 2014 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package viper + +import ( + "bytes" + "fmt" + "os" + "sort" + "strings" + "testing" + "time" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/spf13/pflag" + "github.com/stretchr/testify/assert" +) + +var yamlExample = []byte(`Hacker: true +name: steve +hobbies: +- skateboarding +- snowboarding +- go +clothing: + jacket: leather + trousers: denim +age: 35 +eyes : brown +beard: true +`) + +var tomlExample = []byte(` +title = "TOML Example" + +[owner] +organization = "MongoDB" +Bio = "MongoDB Chief Developer Advocate & Hacker at Large" +dob = 1979-05-27T07:32:00Z # First class dates? Why not?`) + +var jsonExample = []byte(`{ +"id": "0001", +"type": "donut", +"name": "Cake", +"ppu": 0.55, +"batters": { + "batter": [ + { "type": "Regular" }, + { "type": "Chocolate" }, + { "type": "Blueberry" }, + { "type": "Devil's Food" } + ] + } +}`) + +var propertiesExample = []byte(` +p_id: 0001 +p_type: donut +p_name: Cake +p_ppu: 0.55 +p_batters.batter.type: Regular +`) + +var remoteExample = []byte(`{ +"id":"0002", +"type":"cronut", +"newkey":"remote" +}`) + +func initConfigs() { + Reset() + SetConfigType("yaml") + r := bytes.NewReader(yamlExample) + marshalReader(r, v.config) + + SetConfigType("json") + r = bytes.NewReader(jsonExample) + marshalReader(r, v.config) + + SetConfigType("properties") + r = bytes.NewReader(propertiesExample) + marshalReader(r, v.config) + + SetConfigType("toml") + r = bytes.NewReader(tomlExample) + marshalReader(r, v.config) + + SetConfigType("json") + remote := bytes.NewReader(remoteExample) + marshalReader(remote, v.kvstore) +} + +func initYAML() { + Reset() + SetConfigType("yaml") + r := bytes.NewReader(yamlExample) + + marshalReader(r, v.config) +} + +func initJSON() { + Reset() + SetConfigType("json") + r := bytes.NewReader(jsonExample) + + marshalReader(r, v.config) +} + +func initProperties() { + Reset() + SetConfigType("properties") + r := bytes.NewReader(propertiesExample) + + marshalReader(r, v.config) +} + +func initTOML() { + Reset() + SetConfigType("toml") + r := bytes.NewReader(tomlExample) + + marshalReader(r, v.config) +} + +//stubs for PFlag Values +type stringValue string + +func newStringValue(val string, p *string) *stringValue { + *p = val + return (*stringValue)(p) +} + +func (s *stringValue) Set(val string) error { + *s = stringValue(val) + return nil +} + +func (s *stringValue) Type() string { + return "string" +} + +func (s *stringValue) String() string { + return fmt.Sprintf("%s", *s) +} + +func TestBasics(t *testing.T) { + SetConfigFile("/tmp/config.yaml") + assert.Equal(t, "/tmp/config.yaml", v.getConfigFile()) +} + +func TestDefault(t *testing.T) { + SetDefault("age", 45) + assert.Equal(t, 45, Get("age")) +} + +func TestMarshalling(t *testing.T) { + SetConfigType("yaml") + r := bytes.NewReader(yamlExample) + + marshalReader(r, v.config) + assert.True(t, InConfig("name")) + assert.False(t, InConfig("state")) + assert.Equal(t, "steve", Get("name")) + assert.Equal(t, []interface{}{"skateboarding", "snowboarding", "go"}, Get("hobbies")) + assert.Equal(t, map[interface{}]interface{}{"jacket": "leather", "trousers": "denim"}, Get("clothing")) + assert.Equal(t, 35, Get("age")) +} + +func TestOverrides(t *testing.T) { + Set("age", 40) + assert.Equal(t, 40, Get("age")) +} + +func TestDefaultPost(t *testing.T) { + assert.NotEqual(t, "NYC", Get("state")) + SetDefault("state", "NYC") + assert.Equal(t, "NYC", Get("state")) +} + +func TestAliases(t *testing.T) { + RegisterAlias("years", "age") + assert.Equal(t, 40, Get("years")) + Set("years", 45) + assert.Equal(t, 45, Get("age")) +} + +func TestAliasInConfigFile(t *testing.T) { + // the config file specifies "beard". If we make this an alias for + // "hasbeard", we still want the old config file to work with beard. + RegisterAlias("beard", "hasbeard") + assert.Equal(t, true, Get("hasbeard")) + Set("hasbeard", false) + assert.Equal(t, false, Get("beard")) +} + +func TestYML(t *testing.T) { + initYAML() + assert.Equal(t, "steve", Get("name")) +} + +func TestJSON(t *testing.T) { + initJSON() + assert.Equal(t, "0001", Get("id")) +} + +func TestProperties(t *testing.T) { + initProperties() + assert.Equal(t, "0001", Get("p_id")) +} + +func TestTOML(t *testing.T) { + initTOML() + assert.Equal(t, "TOML Example", Get("title")) +} + +func TestRemotePrecedence(t *testing.T) { + initJSON() + + remote := bytes.NewReader(remoteExample) + assert.Equal(t, "0001", Get("id")) + marshalReader(remote, v.kvstore) + assert.Equal(t, "0001", Get("id")) + assert.NotEqual(t, "cronut", Get("type")) + assert.Equal(t, "remote", Get("newkey")) + Set("newkey", "newvalue") + assert.NotEqual(t, "remote", Get("newkey")) + assert.Equal(t, "newvalue", Get("newkey")) + Set("newkey", "remote") +} + +func TestEnv(t *testing.T) { + initJSON() + + BindEnv("id") + BindEnv("f", "FOOD") + + os.Setenv("ID", "13") + os.Setenv("FOOD", "apple") + os.Setenv("NAME", "crunk") + + assert.Equal(t, "13", Get("id")) + assert.Equal(t, "apple", Get("f")) + assert.Equal(t, "Cake", Get("name")) + + AutomaticEnv() + + assert.Equal(t, "crunk", Get("name")) + +} + +func TestEnvPrefix(t *testing.T) { + initJSON() + + SetEnvPrefix("foo") // will be uppercased automatically + BindEnv("id") + BindEnv("f", "FOOD") // not using prefix + + os.Setenv("FOO_ID", "13") + os.Setenv("FOOD", "apple") + os.Setenv("FOO_NAME", "crunk") + + assert.Equal(t, "13", Get("id")) + assert.Equal(t, "apple", Get("f")) + assert.Equal(t, "Cake", Get("name")) + + AutomaticEnv() + + assert.Equal(t, "crunk", Get("name")) +} + +func TestAutoEnv(t *testing.T) { + Reset() + + AutomaticEnv() + os.Setenv("FOO_BAR", "13") + assert.Equal(t, "13", Get("foo_bar")) +} + +func TestAutoEnvWithPrefix(t *testing.T) { + Reset() + + AutomaticEnv() + SetEnvPrefix("Baz") + os.Setenv("BAZ_BAR", "13") + assert.Equal(t, "13", Get("bar")) +} + +func TestSetEnvReplacer(t *testing.T) { + Reset() + + AutomaticEnv() + os.Setenv("REFRESH_INTERVAL", "30s") + + replacer := strings.NewReplacer("-", "_") + SetEnvKeyReplacer(replacer) + + assert.Equal(t, "30s", Get("refresh-interval")) +} + +func TestAllKeys(t *testing.T) { + initConfigs() + + ks := sort.StringSlice{"title", "newkey", "owner", "name", "beard", "ppu", "batters", "hobbies", "clothing", "age", "hacker", "id", "type", "eyes", "p_id", "p_ppu", "p_batters.batter.type", "p_type", "p_name"} + dob, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z") + all := map[string]interface{}{"owner": map[string]interface{}{"organization": "MongoDB", "Bio": "MongoDB Chief Developer Advocate & Hacker at Large", "dob": dob}, "title": "TOML Example", "ppu": 0.55, "eyes": "brown", "clothing": map[interface{}]interface{}{"trousers": "denim", "jacket": "leather"}, "id": "0001", "batters": map[string]interface{}{"batter": []interface{}{map[string]interface{}{"type": "Regular"}, map[string]interface{}{"type": "Chocolate"}, map[string]interface{}{"type": "Blueberry"}, map[string]interface{}{"type": "Devil's Food"}}}, "hacker": true, "beard": true, "hobbies": []interface{}{"skateboarding", "snowboarding", "go"}, "age": 35, "type": "donut", "newkey": "remote", "name": "Cake", "p_id": "0001", "p_ppu": "0.55", "p_name": "Cake", "p_batters.batter.type": "Regular", "p_type": "donut"} + + var allkeys sort.StringSlice + allkeys = AllKeys() + allkeys.Sort() + ks.Sort() + + assert.Equal(t, ks, allkeys) + assert.Equal(t, all, AllSettings()) +} + +func TestCaseInSensitive(t *testing.T) { + assert.Equal(t, true, Get("hacker")) + Set("Title", "Checking Case") + assert.Equal(t, "Checking Case", Get("tItle")) +} + +func TestAliasesOfAliases(t *testing.T) { + RegisterAlias("Foo", "Bar") + RegisterAlias("Bar", "Title") + assert.Equal(t, "Checking Case", Get("FOO")) +} + +func TestRecursiveAliases(t *testing.T) { + RegisterAlias("Baz", "Roo") + RegisterAlias("Roo", "baz") +} + +func TestMarshal(t *testing.T) { + SetDefault("port", 1313) + Set("name", "Steve") + + type config struct { + Port int + Name string + } + + var C config + + err := Marshal(&C) + if err != nil { + t.Fatalf("unable to decode into struct, %v", err) + } + + assert.Equal(t, &C, &config{Name: "Steve", Port: 1313}) + + Set("port", 1234) + err = Marshal(&C) + if err != nil { + t.Fatalf("unable to decode into struct, %v", err) + } + assert.Equal(t, &C, &config{Name: "Steve", Port: 1234}) +} + +func TestBindPFlags(t *testing.T) { + flagSet := pflag.NewFlagSet("test", pflag.ContinueOnError) + + var testValues = map[string]*string{ + "host": nil, + "port": nil, + "endpoint": nil, + } + + var mutatedTestValues = map[string]string{ + "host": "localhost", + "port": "6060", + "endpoint": "/public", + } + + for name, _ := range testValues { + testValues[name] = flagSet.String(name, "", "test") + } + + err := BindPFlags(flagSet) + if err != nil { + t.Fatalf("error binding flag set, %v", err) + } + + flagSet.VisitAll(func(flag *pflag.Flag) { + flag.Value.Set(mutatedTestValues[flag.Name]) + flag.Changed = true + }) + + for name, expected := range mutatedTestValues { + assert.Equal(t, Get(name), expected) + } + +} + +func TestBindPFlag(t *testing.T) { + var testString = "testing" + var testValue = newStringValue(testString, &testString) + + flag := &pflag.Flag{ + Name: "testflag", + Value: testValue, + Changed: false, + } + + BindPFlag("testvalue", flag) + + assert.Equal(t, testString, Get("testvalue")) + + flag.Value.Set("testing_mutate") + flag.Changed = true //hack for pflag usage + + assert.Equal(t, "testing_mutate", Get("testvalue")) + +} + +func TestBoundCaseSensitivity(t *testing.T) { + + assert.Equal(t, "brown", Get("eyes")) + + BindEnv("eYEs", "TURTLE_EYES") + os.Setenv("TURTLE_EYES", "blue") + + assert.Equal(t, "blue", Get("eyes")) + + var testString = "green" + var testValue = newStringValue(testString, &testString) + + flag := &pflag.Flag{ + Name: "eyeballs", + Value: testValue, + Changed: true, + } + + BindPFlag("eYEs", flag) + assert.Equal(t, "green", Get("eyes")) + +} + +func TestSizeInBytes(t *testing.T) { + input := map[string]uint{ + "": 0, + "b": 0, + "12 bytes": 0, + "200000000000gb": 0, + "12 b": 12, + "43 MB": 43 * (1 << 20), + "10mb": 10 * (1 << 20), + "1gb": 1 << 30, + } + + for str, expected := range input { + assert.Equal(t, expected, parseSizeInBytes(str), str) + } +} + +func TestFindsNestedKeys(t *testing.T) { + initConfigs() + dob, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z") + + Set("super", map[string]interface{}{ + "deep": map[string]interface{}{ + "nested": "value", + }, + }) + + expected := map[string]interface{}{ + "super": map[string]interface{}{ + "deep": map[string]interface{}{ + "nested": "value", + }, + }, + "super.deep": map[string]interface{}{ + "nested": "value", + }, + "super.deep.nested": "value", + "owner.organization": "MongoDB", + "batters.batter": []interface{}{ + map[string]interface{}{ + "type": "Regular", + }, + map[string]interface{}{ + "type": "Chocolate", + }, + map[string]interface{}{ + "type": "Blueberry", + }, + map[string]interface{}{ + "type": "Devil's Food", + }, + }, + "hobbies": []interface{}{ + "skateboarding", "snowboarding", "go", + }, + "title": "TOML Example", + "newkey": "remote", + "batters": map[string]interface{}{ + "batter": []interface{}{ + map[string]interface{}{ + "type": "Regular", + }, + map[string]interface{}{ + "type": "Chocolate", + }, map[string]interface{}{ + "type": "Blueberry", + }, map[string]interface{}{ + "type": "Devil's Food", + }, + }, + }, + "eyes": "brown", + "age": 35, + "owner": map[string]interface{}{ + "organization": "MongoDB", + "Bio": "MongoDB Chief Developer Advocate & Hacker at Large", + "dob": dob, + }, + "owner.Bio": "MongoDB Chief Developer Advocate & Hacker at Large", + "type": "donut", + "id": "0001", + "name": "Cake", + "hacker": true, + "ppu": 0.55, + "clothing": map[interface{}]interface{}{ + "jacket": "leather", + "trousers": "denim", + }, + "clothing.jacket": "leather", + "clothing.trousers": "denim", + "owner.dob": dob, + "beard": true, + } + + for key, expectedValue := range expected { + + assert.Equal(t, expectedValue, v.Get(key)) + } + +} + +func TestReadBufConfig(t *testing.T) { + v := New() + v.SetConfigType("yaml") + v.ReadConfig(bytes.NewBuffer(yamlExample)) + t.Log(v.AllKeys()) + + assert.True(t, v.InConfig("name")) + assert.False(t, v.InConfig("state")) + assert.Equal(t, "steve", v.Get("name")) + assert.Equal(t, []interface{}{"skateboarding", "snowboarding", "go"}, v.Get("hobbies")) + assert.Equal(t, map[interface{}]interface{}{"jacket": "leather", "trousers": "denim"}, v.Get("clothing")) + assert.Equal(t, 35, v.Get("age")) +} diff --git a/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/backend.go b/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/backend.go new file mode 100644 index 00000000..bfe894dc --- /dev/null +++ b/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/backend.go @@ -0,0 +1,32 @@ +// Package backend provides the K/V store interface for crypt backends. +package backend + +// Response represents a response from a backend store. +type Response struct { + Value []byte + Error error +} + +// KVPair holds both a key and value when reading a list. +type KVPair struct { + Key string + Value []byte +} + +type KVPairs []*KVPair + +// A Store is a K/V store backend that retrieves and sets, and monitors +// data in a K/V store. +type Store interface { + // Get retrieves a value from a K/V store for the provided key. + Get(key string) ([]byte, error) + + // List retrieves all keys and values under a provided key. + List(key string) (KVPairs, error) + + // Set sets the provided key to value. + Set(key string, value []byte) error + + // Watch monitors a K/V store for changes to key. + Watch(key string, stop chan bool) <-chan *Response +} diff --git a/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/consul/consul.go b/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/consul/consul.go new file mode 100644 index 00000000..063f9986 --- /dev/null +++ b/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/consul/consul.go @@ -0,0 +1,87 @@ +package consul + +import ( + "fmt" + "strings" + "time" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/armon/consul-api" +) + +type Client struct { + client *consulapi.KV + waitIndex uint64 +} + +func New(machines []string) (*Client, error) { + conf := consulapi.DefaultConfig() + if len(machines) > 0 { + conf.Address = machines[0] + } + client, err := consulapi.NewClient(conf) + if err != nil { + return nil, err + } + return &Client{client.KV(), 0}, nil +} + +func (c *Client) Get(key string) ([]byte, error) { + kv, _, err := c.client.Get(key, nil) + if err != nil { + return nil, err + } + if kv == nil { + return nil, fmt.Errorf("Key ( %s ) was not found.", key) + } + return kv.Value, nil +} + +func (c *Client) List(key string) (backend.KVPairs, error) { + pairs, _, err := c.client.List(key, nil) + if err != nil { + return nil, err + } + if err != nil { + return nil, err + } + ret := make(backend.KVPairs, len(pairs), len(pairs)) + for i, kv := range pairs { + ret[i] = &backend.KVPair{Key: kv.Key, Value: kv.Value} + } + return ret, nil +} + +func (c *Client) Set(key string, value []byte) error { + key = strings.TrimPrefix(key, "/") + kv := &consulapi.KVPair{ + Key: key, + Value: value, + } + _, err := c.client.Put(kv, nil) + return err +} + +func (c *Client) Watch(key string, stop chan bool) <-chan *backend.Response { + respChan := make(chan *backend.Response, 0) + go func() { + for { + opts := consulapi.QueryOptions{ + WaitIndex: c.waitIndex, + } + keypair, meta, err := c.client.Get(key, &opts) + if keypair == nil && err == nil { + err = fmt.Errorf("Key ( %s ) was not found.", key) + } + if err != nil { + respChan <- &backend.Response{nil, err} + time.Sleep(time.Second * 5) + continue + } + c.waitIndex = meta.LastIndex + respChan <- &backend.Response{keypair.Value, nil} + } + }() + return respChan +} diff --git a/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/etcd/etcd.go b/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/etcd/etcd.go new file mode 100644 index 00000000..b8f0dd19 --- /dev/null +++ b/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/etcd/etcd.go @@ -0,0 +1,84 @@ +package etcd + +import ( + "errors" + "time" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend" + + goetcd "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd" +) + +type Client struct { + client *goetcd.Client + waitIndex uint64 +} + +func New(machines []string) (*Client, error) { + return &Client{goetcd.NewClient(machines), 0}, nil +} + +func (c *Client) Get(key string) ([]byte, error) { + resp, err := c.client.Get(key, false, false) + if err != nil { + return nil, err + } + return []byte(resp.Node.Value), nil +} + +func addKVPairs(node *goetcd.Node, list backend.KVPairs) backend.KVPairs { + if node.Dir { + for _, n := range node.Nodes { + list = addKVPairs(n, list) + } + return list + } + return append(list, &backend.KVPair{Key: node.Key, Value: []byte(node.Value)}) +} + +func (c *Client) List(key string) (backend.KVPairs, error) { + resp, err := c.client.Get(key, false, true) + if err != nil { + return nil, err + } + if !resp.Node.Dir { + return nil, errors.New("key is not a directory") + } + list := addKVPairs(resp.Node, nil) + return list, nil +} + +func (c *Client) Set(key string, value []byte) error { + _, err := c.client.Set(key, string(value), 0) + return err +} + +func (c *Client) Watch(key string, stop chan bool) <-chan *backend.Response { + respChan := make(chan *backend.Response, 0) + go func() { + for { + var resp *goetcd.Response + var err error + // if c.waitIndex == 0 { + // resp, err = c.client.Get(key, false, false) + // if err != nil { + // respChan <- &backend.Response{nil, err} + // time.Sleep(time.Second * 5) + // continue + // } + // c.waitIndex = resp.EtcdIndex + // respChan <- &backend.Response{[]byte(resp.Node.Value), nil} + // } + // resp, err = c.client.Watch(key, c.waitIndex+1, false, nil, stop) + resp, err = c.client.Watch(key, 0, false, nil, stop) + if err != nil { + respChan <- &backend.Response{nil, err} + time.Sleep(time.Second * 5) + continue + } + c.waitIndex = resp.Node.ModifiedIndex + respChan <- &backend.Response{[]byte(resp.Node.Value), nil} + } + }() + return respChan +} diff --git a/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/mock/mock.go b/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/mock/mock.go new file mode 100644 index 00000000..c7eb1cb2 --- /dev/null +++ b/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/mock/mock.go @@ -0,0 +1,61 @@ +package mock + +import ( + "errors" + "path" + "strings" + "time" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend" +) + +var mockedStore map[string][]byte + +type Client struct{} + +func New(machines []string) (*Client, error) { + if mockedStore == nil { + mockedStore = make(map[string][]byte, 2) + } + return &Client{}, nil +} + +func (c *Client) Get(key string) ([]byte, error) { + if v, ok := mockedStore[key]; ok { + return v, nil + } + err := errors.New("Could not find key: " + key) + return nil, err +} + +func (c *Client) List(key string) (backend.KVPairs, error) { + var list backend.KVPairs + dir := path.Clean(key) + "/" + for k, v := range mockedStore { + if strings.HasPrefix(k, dir) { + list = append(list, &backend.KVPair{Key: k, Value: v}) + } + } + return list, nil +} + +func (c *Client) Set(key string, value []byte) error { + mockedStore[key] = value + return nil +} + +func (c *Client) Watch(key string, stop chan bool) <-chan *backend.Response { + respChan := make(chan *backend.Response, 0) + go func() { + for { + b, err := c.Get(key) + if err != nil { + respChan <- &backend.Response{nil, err} + time.Sleep(time.Second * 5) + continue + } + respChan <- &backend.Response{b, nil} + } + }() + return respChan +} diff --git a/Godeps/_workspace/src/github.com/xordataexchange/crypt/config/README.md b/Godeps/_workspace/src/github.com/xordataexchange/crypt/config/README.md new file mode 100644 index 00000000..c4f79326 --- /dev/null +++ b/Godeps/_workspace/src/github.com/xordataexchange/crypt/config/README.md @@ -0,0 +1,86 @@ +# crypt/config + +## Usage + +### Get configuration from a backend + +``` +package main + +import ( + "fmt" + "log" + "os" + + "github.com/xordataexchange/crypt/config" +) + +var ( + key = "/app/config" + secretKeyring = ".secring.gpg" +) + +func main() { + kr, err := os.Open(secretKeyring) + if err != nil { + log.Fatal(err) + } + defer kr.Close() + machines := []string{"http://127.0.0.1:4001"} + cm, err := config.NewEtcdConfigManager(machines, kr) + if err != nil { + log.Fatal(err) + } + value, err := cm.Get(key) + if err != nil { + log.Fatal(err) + } + fmt.Printf("%s\n", value) +} +``` + +### Monitor backend for configuration changes + +``` +package main + +import ( + "fmt" + "log" + "os" + + "github.com/xordataexchange/crypt/config" +) + +var ( + key = "/app/config" + secretKeyring = ".secring.gpg" +) + +func main() { + kr, err := os.Open(secretKeyring) + if err != nil { + log.Fatal(err) + } + defer kr.Close() + machines := []string{"http://127.0.0.1:4001"} + cm, err := config.NewEtcdConfigManager(machines, kr) + if err != nil { + log.Fatal(err) + } + stop := make(chan bool, 0) + resp := cm.Watch(key, stop) + if err != nil { + log.Fatal(err) + } + for { + select { + case r := <-resp: + if r.Error != nil { + fmt.Println(r.Error.Error()) + } + fmt.Printf("%s\n", r.Value) + } + } +} +``` diff --git a/Godeps/_workspace/src/github.com/xordataexchange/crypt/config/config.go b/Godeps/_workspace/src/github.com/xordataexchange/crypt/config/config.go new file mode 100644 index 00000000..16adf627 --- /dev/null +++ b/Godeps/_workspace/src/github.com/xordataexchange/crypt/config/config.go @@ -0,0 +1,201 @@ +package config + +import ( + "bytes" + "io" + "io/ioutil" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend" + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/consul" + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/etcd" + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/xordataexchange/crypt/encoding/secconf" +) + +type KVPair struct { + backend.KVPair +} + +type KVPairs []*KVPair + +type configManager struct { + keystore []byte + store backend.Store +} + +// A ConfigManager retrieves and decrypts configuration from a key/value store. +type ConfigManager interface { + Get(key string) ([]byte, error) + List(key string) (KVPairs, error) + Set(key string, value []byte) error + Watch(key string, stop chan bool) <-chan *Response +} + +type standardConfigManager struct { + store backend.Store +} + +func NewStandardConfigManager(client backend.Store) (ConfigManager, error) { + return standardConfigManager{client}, nil +} + +func NewConfigManager(client backend.Store, keystore io.Reader) (ConfigManager, error) { + bytes, err := ioutil.ReadAll(keystore) + if err != nil { + return nil, err + } + return configManager{bytes, client}, nil +} + +// NewStandardEtcdConfigManager returns a new ConfigManager backed by etcd. +func NewStandardEtcdConfigManager(machines []string) (ConfigManager, error) { + store, err := etcd.New(machines) + if err != nil { + return nil, err + } + + return NewStandardConfigManager(store) +} + +// NewStandardConsulConfigManager returns a new ConfigManager backed by consul. +func NewStandardConsulConfigManager(machines []string) (ConfigManager, error) { + store, err := consul.New(machines) + if err != nil { + return nil, err + } + return NewStandardConfigManager(store) +} + +// NewEtcdConfigManager returns a new ConfigManager backed by etcd. +// Data will be encrypted. +func NewEtcdConfigManager(machines []string, keystore io.Reader) (ConfigManager, error) { + store, err := etcd.New(machines) + if err != nil { + return nil, err + } + return NewConfigManager(store, keystore) +} + +// NewConsulConfigManager returns a new ConfigManager backed by consul. +// Data will be encrypted. +func NewConsulConfigManager(machines []string, keystore io.Reader) (ConfigManager, error) { + store, err := consul.New(machines) + if err != nil { + return nil, err + } + return NewConfigManager(store, keystore) +} + +// Get retrieves and decodes a secconf value stored at key. +func (c configManager) Get(key string) ([]byte, error) { + value, err := c.store.Get(key) + if err != nil { + return nil, err + } + return secconf.Decode(value, bytes.NewBuffer(c.keystore)) +} + +// Get retrieves a value stored at key. +// convenience function, no additional value provided over +// `etcdctl` +func (c standardConfigManager) Get(key string) ([]byte, error) { + value, err := c.store.Get(key) + if err != nil { + return nil, err + } + return value, err +} + +// List retrieves and decodes all secconf value stored under key. +func (c configManager) List(key string) (KVPairs, error) { + list, err := c.store.List(key) + retList := make(KVPairs, len(list)) + if err != nil { + return nil, err + } + for i, kv := range list { + retList[i].Key = kv.Key + retList[i].Value, err = secconf.Decode(kv.Value, bytes.NewBuffer(c.keystore)) + if err != nil { + return nil, err + } + } + return retList, nil +} + +// List retrieves all values under key. +// convenience function, no additional value provided over +// `etcdctl` +func (c standardConfigManager) List(key string) (KVPairs, error) { + list, err := c.store.List(key) + retList := make(KVPairs, len(list)) + if err != nil { + return nil, err + } + for i, kv := range list { + retList[i].Key = kv.Key + retList[i].Value = kv.Value + } + return retList, err +} + +// Set will put a key/value into the data store +// and encode it with secconf +func (c configManager) Set(key string, value []byte) error { + encodedValue, err := secconf.Encode(value, bytes.NewBuffer(c.keystore)) + if err == nil { + err = c.store.Set(key, encodedValue) + } + return err +} + +// Set will put a key/value into the data store +func (c standardConfigManager) Set(key string, value []byte) error { + err := c.store.Set(key, value) + return err +} + +type Response struct { + Value []byte + Error error +} + +func (c configManager) Watch(key string, stop chan bool) <-chan *Response { + resp := make(chan *Response, 0) + backendResp := c.store.Watch(key, stop) + go func() { + for { + select { + case <-stop: + return + case r := <-backendResp: + if r.Error != nil { + resp <- &Response{nil, r.Error} + continue + } + value, err := secconf.Decode(r.Value, bytes.NewBuffer(c.keystore)) + resp <- &Response{value, err} + } + } + }() + return resp +} + +func (c standardConfigManager) Watch(key string, stop chan bool) <-chan *Response { + resp := make(chan *Response, 0) + backendResp := c.store.Watch(key, stop) + go func() { + for { + select { + case <-stop: + return + case r := <-backendResp: + if r.Error != nil { + resp <- &Response{nil, r.Error} + continue + } + resp <- &Response{r.Value, nil} + } + } + }() + return resp +} diff --git a/Godeps/_workspace/src/github.com/xordataexchange/crypt/config/config_test.go b/Godeps/_workspace/src/github.com/xordataexchange/crypt/config/config_test.go new file mode 100644 index 00000000..5e8bdd11 --- /dev/null +++ b/Godeps/_workspace/src/github.com/xordataexchange/crypt/config/config_test.go @@ -0,0 +1,257 @@ +package config + +import ( + "bytes" + "reflect" + "testing" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/xordataexchange/crypt/backend/mock" +) + +var pubring = `-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG/MacGPG2 v2.0.22 (Darwin) +Comment: GPGTools - https://gpgtools.org + +mQENBFRClxIBCACjlm8e2mI5TmeigPuF4HJqNxc6AFLoCsE3MQ6VtdEVqidXZ06L +m7uIXYc3IfvAlID+1KrUJnO2IgLEMmXKSDI5aOch7VaeoXLKMt7yAX+N6DHaZl4l +eUGlfyIuBGD7FY2rv4hHo2wOmlq/chnNA4T7wb2XzeaAjvvoxcedMZ2npVimjwsl +MNDxSxYPlHR6lJgfYJHAxcWn7ZQJW2Kllv9jMQwzGqW4fxuKRhe20KStE/4+K9gL +GWv6OoE2gcGLoXliIMchHobY0GEvVx+YUv5jAItRSXq4ajYjFLtsWLz6FYtK9CoO +Va6T5EGqozKST/olW/FMmKLOTzpAilyoKB/HABEBAAG0LWFwcCAoYXBwIGNvbmZp +Z3VyYXRpb24ga2V5KSA8YXBwQGV4YW1wbGUuY29tPokBNwQTAQoAIQUCVEKXEgIb +AwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRA8TymBhIANsjB1CACi4kqqWNSq +AID7LmMswh5FQDEPkI/WA0h75xead11FVSdvtjWANY4Wob8RBjeZNT0TaCa0IAoo +k+tLqA5xNbbvalOPV2zfr86BcGMhIs900++PuVjOb7XaJPsEt5JwtzuLM+eDLIVh +vMI7hQtgB39O8/AsWEW/E/JlVtHcrsQ7LfcQYmNZVSnL71a8w4G+A6Sto89fvpjY +h9/M4+aHqMhO/NLLp8Ylj5TlyiWKHZlx5ufl2ejWMUot3wFhYADHPkhydmQV9IY1 +zzIpmB/75kvZqC4p92k7l8Ra82o+T75/dNy0HcgvgrfZQttxIM0WPEyVF5NjicSo +akoggAAslhCNuQENBFRClxIBCADJltx4EgkFScH/EAmO6+mZb6+pcpjY/H97bX4w +KUrQSDZjDAhoxsInKgqHwAo3QY261eYrAyHvoTA2kRAaVrYWeGu3RxMmX5LTjFsX +IW44ocTJK1XziUQympgIEayOUHt+XJaMGL8RKXvNgttGkr2VPD0IWJCOaBr8ZxUG +Fm/pRFeBe6tX02RVKx4QFPqCnb76bkvR1cNeFsV5eEz0WNRYzena+lD6Oqh074tk +oC9Uwl7D0l7xq17HNqAqHdMIO/T/TMPYyb7vskHPL9g8EJSgU55Z2Cjx3IlbJCpA +204cbbak4h99kgAqb4O5jT3gDe03NzWXCeQVKmacahusqNxzABEBAAGJAR8EGAEK +AAkFAlRClxICGwwACgkQPE8pgYSADbJFTwf/d6XIv8/BxaP5TB12FxRXevOVenYe +xR6O0rXDKFkP54LHSh2uaJbjLHevF0tuiNLFWq9RPhVjC012OLdo+2ygEFwNfikd +1SMbUIkuZ6Nu2MvCdrpAwbcvLgeoe8bqf1B6EIb31/OxCmtHujpVw6cSAnpAVyYo +PjPtEpcNatIHbOna4KANxwv1Rmc6XDxWIB0RIlbdZDUhEdLovLLWGjm4J++Cnn2n +OFdZyyUxwYTjDCMWwsYrG2oPZ0Yle6fKEXX30E+dN9NSV1i+dJAYQi0am6augpg+ +LmFWxQ6JPmUJVDay9wo6g2D4KbJQybSh8lmqpenHnKD1m/gCGadPmMl6Rw== +=FKbO +-----END PGP PUBLIC KEY BLOCK-----` + +var secring = ` +-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: GnuPG/MacGPG2 v2.0.22 (Darwin) +Comment: GPGTools - https://gpgtools.org + +lQOYBFRClxIBCACjlm8e2mI5TmeigPuF4HJqNxc6AFLoCsE3MQ6VtdEVqidXZ06L +m7uIXYc3IfvAlID+1KrUJnO2IgLEMmXKSDI5aOch7VaeoXLKMt7yAX+N6DHaZl4l +eUGlfyIuBGD7FY2rv4hHo2wOmlq/chnNA4T7wb2XzeaAjvvoxcedMZ2npVimjwsl +MNDxSxYPlHR6lJgfYJHAxcWn7ZQJW2Kllv9jMQwzGqW4fxuKRhe20KStE/4+K9gL +GWv6OoE2gcGLoXliIMchHobY0GEvVx+YUv5jAItRSXq4ajYjFLtsWLz6FYtK9CoO +Va6T5EGqozKST/olW/FMmKLOTzpAilyoKB/HABEBAAEAB/wKvEBo68JJaiH2nJ9P +qas92YVZMD9Al2rBoU2zOR4nsqW9SybGQP89aOHgQNyBcV1xG79lh8Eii+MsQUsZ +IMQcV2GKV5sjyDWScQ8yHjNi5SuBs85sMs5s5XB2nkvyU6JF9J5QETicprgw2x84 +AIn1buvvGTs4vD6/h7Hcri5fRimBvh+dcH/48nXPH56cZEPl/53tJt/lWwlfFBX1 +phZMIPoHT1kihEt//Hn4raw30R/bm0CJP/PtiyRkNeebzJsIJXtzG30B8YZb6c/h +TtobA4F4ZWtEEwotPBFtx4clS/+2amc+PY+ZGTKXjzvQChaz50gvtSUp9ns9X/G+ +T/vRBADC3dNGE2Ut8DRE2C/MQ7DdZdHdxaHJSMV+08xI/OSDOxp3ea1S2cbjniIG +cnuQ8ZXD4hWDKSZTGs2L4awdsL5eIhqACnxT3LXm0TBwBWDzE3CQZUQGc+2pFgDb +1Xc/By+OZgFCDlJhHuhK4Lf9EsH3HbV/Cmn8sDD+dKazLxUF1wQA1uiH8X/8dgcQ +uH/RSH2C7+Sr2B2Tpha9kngg4/cB31v3YaBV2t55zBvhSObxCM97gl6FadrEjJsw +FvN04DMWhlt2xWbLnt1v4suVo8V1Are4vqP8G/mWhJou2Ps/65nsFqStNHMA+xjQ +h8hAqY/9Mmu9Vm6WNRON0WCT3Snil5ED/0zUGI2qogw35Uzu448FrrYlh97kj3wu +RzOZB/mty2pVj9eJO0z6E3C6sYLvbxrd8TyFzs4fTP7WlwG5FMJu/I4cEBqUJ/rr ++ulSV/HH7zLpD6hWZbuRYhY8uskkVH50be4bb7MrXtoeDKrKfM4+BKf39QaBDNfI +jD0Perf+Ll0aRBm0LWFwcCAoYXBwIGNvbmZpZ3VyYXRpb24ga2V5KSA8YXBwQGV4 +YW1wbGUuY29tPokBNwQTAQoAIQUCVEKXEgIbAwULCQgHAwUVCgkICwUWAgMBAAIe +AQIXgAAKCRA8TymBhIANsjB1CACi4kqqWNSqAID7LmMswh5FQDEPkI/WA0h75xea +d11FVSdvtjWANY4Wob8RBjeZNT0TaCa0IAook+tLqA5xNbbvalOPV2zfr86BcGMh +Is900++PuVjOb7XaJPsEt5JwtzuLM+eDLIVhvMI7hQtgB39O8/AsWEW/E/JlVtHc +rsQ7LfcQYmNZVSnL71a8w4G+A6Sto89fvpjYh9/M4+aHqMhO/NLLp8Ylj5TlyiWK +HZlx5ufl2ejWMUot3wFhYADHPkhydmQV9IY1zzIpmB/75kvZqC4p92k7l8Ra82o+ +T75/dNy0HcgvgrfZQttxIM0WPEyVF5NjicSoakoggAAslhCNnQOYBFRClxIBCADJ +ltx4EgkFScH/EAmO6+mZb6+pcpjY/H97bX4wKUrQSDZjDAhoxsInKgqHwAo3QY26 +1eYrAyHvoTA2kRAaVrYWeGu3RxMmX5LTjFsXIW44ocTJK1XziUQympgIEayOUHt+ +XJaMGL8RKXvNgttGkr2VPD0IWJCOaBr8ZxUGFm/pRFeBe6tX02RVKx4QFPqCnb76 +bkvR1cNeFsV5eEz0WNRYzena+lD6Oqh074tkoC9Uwl7D0l7xq17HNqAqHdMIO/T/ +TMPYyb7vskHPL9g8EJSgU55Z2Cjx3IlbJCpA204cbbak4h99kgAqb4O5jT3gDe03 +NzWXCeQVKmacahusqNxzABEBAAEAB/47pozhaLDLpEonz9aMOImckfxgPx00Y+7T +FpC27pkJLb0OLPLWEi5ESX/pMG21cQvfw8iCZMBneIJcOyuRJ6Rk3Mg+6OSlP7Wi +LI+NtiI31sJ0poKd+Dm6YZ1oEdbGG9GXEA2qMe5jxSsxoi2BYg2AOd1zeUV5JhwK +IPSLIxuFYeDV/erv0n73Lob/Xj7SzhwRNQUJuG9Ak+maha1oqHwTuzPox9e+kSkK ++VOhW+9oTukxsg8lCD351X/VvHeJgZkfTshLbQdAbMUlBQ00O7TyprFFLKcd0MNL +gdVz5vHson5NyEzxsCbnV0Hty5Am00r1hm3Y89/k9HmBr3f+IH6JBADK0ZN9m4Br +xpc2fou40/HBKBPk/5sJoOcHklBM7j4COYqloYaYliZRKmeWfH3gPhYW+EOqsZtv +BPZaS7RL0IU8GoC1GfIrHJ+4GwiZQm6URDvEVSWsWiaUkI+cnK1HX8zsWHq48tqF +yVSOZ05Lh3Id65s3mnXzF3/zzQLMmKm1OwQA/nLDZSMRdr/WWW2nFpf5QH0y9eI3 +VU/4/QSIBLFL5iAXOebHDseCr7/G/W6hn00VTQIUq3UKDi+gy9epm9aBrdNyF3Ey +PvuACFLduF4ZnPOeZ1YrBxCRPHnGf+3So2Kcl9c1+RzMJ/qY+lZCU6pMCgCkeAZP +iTGeuExKr9OrIikD/Au6yH+Oc2GEvorhoWcerEeXFvvx1S+9oJBKnJl9y6PRJacy +wkZ354RyD9AojMJliibaHdAdpGSrOL8NEYQGy/3YzW1sMS2GBw6yZJ/GPCRDVEaE +Nkbi/Aj3Shh2+w/jeYsUgrJkZY/UeoJt/mdUO1+loRoqTdlOOJLpPcyF6WzQQU+J +AR8EGAEKAAkFAlRClxICGwwACgkQPE8pgYSADbJFTwf/d6XIv8/BxaP5TB12FxRX +evOVenYexR6O0rXDKFkP54LHSh2uaJbjLHevF0tuiNLFWq9RPhVjC012OLdo+2yg +EFwNfikd1SMbUIkuZ6Nu2MvCdrpAwbcvLgeoe8bqf1B6EIb31/OxCmtHujpVw6cS +AnpAVyYoPjPtEpcNatIHbOna4KANxwv1Rmc6XDxWIB0RIlbdZDUhEdLovLLWGjm4 +J++Cnn2nOFdZyyUxwYTjDCMWwsYrG2oPZ0Yle6fKEXX30E+dN9NSV1i+dJAYQi0a +m6augpg+LmFWxQ6JPmUJVDay9wo6g2D4KbJQybSh8lmqpenHnKD1m/gCGadPmMl6 +Rw== +=RvPL +-----END PGP PRIVATE KEY BLOCK----- +` + +func Test_StandardSet_BasePath(t *testing.T) { + key := "foo" + value := []byte("bar") + + store, err := mock.New([]string{}) + if err != nil { + t.Errorf("Error creating backend: %s\n", err.Error()) + } + cm, err := NewStandardConfigManager(store) + if err != nil { + t.Errorf("Error creating config manager: %s\n", err.Error()) + } + err = cm.Set(key, value) + if err != nil { + t.Errorf("Error adding key: %s\n", err.Error()) + } +} + +func Test_StandardGet_BasePath(t *testing.T) { + key := "foo" + value := []byte("bar") + + store, err := mock.New([]string{}) + if err != nil { + t.Errorf("Error creating backend: %s\n", err.Error()) + } + cm, err := NewStandardConfigManager(store) + if err != nil { + t.Errorf("Error creating config manager: %s\n", err.Error()) + } + storedValue, err := cm.Get(key) + if err != nil { + t.Errorf("Error getting key: %s\n", err.Error()) + } + if !reflect.DeepEqual(storedValue, value) { + t.Errorf("Two values did not match: %s\n", err.Error()) + } +} + +func Test_StandardGet_AlternatePath_NoKey(t *testing.T) { + key := "doesnotexist" + + store, err := mock.New([]string{}) + if err != nil { + t.Errorf("Error creating backend: %s\n", err.Error()) + } + cm, err := NewStandardConfigManager(store) + if err != nil { + t.Errorf("Error creating config manager: %s\n", err.Error()) + } + _, err = cm.Get(key) + if err == nil { + t.Errorf("Did not get expected error\n") + } +} + +func Test_StandardWatch_BasePath(t *testing.T) { + key := "foo" + + store, err := mock.New([]string{}) + if err != nil { + t.Errorf("Error creating backend: %s\n", err.Error()) + } + cm, err := NewStandardConfigManager(store) + if err != nil { + t.Errorf("Error creating config manager: %s\n", err.Error()) + } + timeout := make(chan bool, 0) + resp := cm.Watch(key, timeout) + select { + case r := <-resp: + if r.Error != nil { + t.Errorf("Error watching value: %s\n", r.Error.Error()) + } + } +} + +func Test_Set_BasePath(t *testing.T) { + key := "foo_enc" + value := []byte("bar_enc") + + store, err := mock.New([]string{}) + if err != nil { + t.Errorf("Error creating backend: %s\n", err.Error()) + } + cm, err := NewConfigManager(store, bytes.NewBufferString(pubring)) + if err != nil { + t.Errorf("Error creating config manager: %s\n", err.Error()) + } + err = cm.Set(key, value) + if err != nil { + t.Errorf("Error adding key: %s\n", err.Error()) + } +} + +func Test_Get_BasePath(t *testing.T) { + key := "foo_enc" + value := []byte("bar_enc") + + store, err := mock.New([]string{}) + if err != nil { + t.Errorf("Error creating backend: %s\n", err.Error()) + } + cm, err := NewConfigManager(store, bytes.NewBufferString(secring)) + if err != nil { + t.Errorf("Error creating config manager: %s\n", err.Error()) + } + storedValue, err := cm.Get(key) + if err != nil { + t.Errorf("Error getting key: %s\n", err.Error()) + } + if !reflect.DeepEqual(storedValue, value) { + t.Errorf("Two values did not match: %s\n", err.Error()) + } +} + +func Test_Get_AlternatePath_NoKey(t *testing.T) { + key := "doesnotexist_enc" + + store, err := mock.New([]string{}) + if err != nil { + t.Errorf("Error creating backend: %s\n", err.Error()) + } + cm, err := NewConfigManager(store, bytes.NewBufferString(secring)) + if err != nil { + t.Errorf("Error creating config manager: %s\n", err.Error()) + } + _, err = cm.Get(key) + if err == nil { + t.Errorf("Did not get expected error\n") + } +} + +func Test_Watch_BasePath(t *testing.T) { + key := "foo_enc" + + store, err := mock.New([]string{}) + if err != nil { + t.Errorf("Error creating backend: %s\n", err.Error()) + } + cm, err := NewConfigManager(store, bytes.NewBufferString(secring)) + if err != nil { + t.Errorf("Error creating config manager: %s\n", err.Error()) + } + timeout := make(chan bool, 0) + resp := cm.Watch(key, timeout) + select { + case r := <-resp: + if r.Error != nil { + t.Errorf("Error watching value: %s\n", r.Error.Error()) + } + } +} diff --git a/Godeps/_workspace/src/github.com/xordataexchange/crypt/encoding/secconf/keyring_test.go b/Godeps/_workspace/src/github.com/xordataexchange/crypt/encoding/secconf/keyring_test.go new file mode 100644 index 00000000..c902d35d --- /dev/null +++ b/Godeps/_workspace/src/github.com/xordataexchange/crypt/encoding/secconf/keyring_test.go @@ -0,0 +1,95 @@ +package secconf + +var pubring = `-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG/MacGPG2 v2.0.22 (Darwin) +Comment: GPGTools - https://gpgtools.org + +mQENBFRClxIBCACjlm8e2mI5TmeigPuF4HJqNxc6AFLoCsE3MQ6VtdEVqidXZ06L +m7uIXYc3IfvAlID+1KrUJnO2IgLEMmXKSDI5aOch7VaeoXLKMt7yAX+N6DHaZl4l +eUGlfyIuBGD7FY2rv4hHo2wOmlq/chnNA4T7wb2XzeaAjvvoxcedMZ2npVimjwsl +MNDxSxYPlHR6lJgfYJHAxcWn7ZQJW2Kllv9jMQwzGqW4fxuKRhe20KStE/4+K9gL +GWv6OoE2gcGLoXliIMchHobY0GEvVx+YUv5jAItRSXq4ajYjFLtsWLz6FYtK9CoO +Va6T5EGqozKST/olW/FMmKLOTzpAilyoKB/HABEBAAG0LWFwcCAoYXBwIGNvbmZp +Z3VyYXRpb24ga2V5KSA8YXBwQGV4YW1wbGUuY29tPokBNwQTAQoAIQUCVEKXEgIb +AwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRA8TymBhIANsjB1CACi4kqqWNSq +AID7LmMswh5FQDEPkI/WA0h75xead11FVSdvtjWANY4Wob8RBjeZNT0TaCa0IAoo +k+tLqA5xNbbvalOPV2zfr86BcGMhIs900++PuVjOb7XaJPsEt5JwtzuLM+eDLIVh +vMI7hQtgB39O8/AsWEW/E/JlVtHcrsQ7LfcQYmNZVSnL71a8w4G+A6Sto89fvpjY +h9/M4+aHqMhO/NLLp8Ylj5TlyiWKHZlx5ufl2ejWMUot3wFhYADHPkhydmQV9IY1 +zzIpmB/75kvZqC4p92k7l8Ra82o+T75/dNy0HcgvgrfZQttxIM0WPEyVF5NjicSo +akoggAAslhCNuQENBFRClxIBCADJltx4EgkFScH/EAmO6+mZb6+pcpjY/H97bX4w +KUrQSDZjDAhoxsInKgqHwAo3QY261eYrAyHvoTA2kRAaVrYWeGu3RxMmX5LTjFsX +IW44ocTJK1XziUQympgIEayOUHt+XJaMGL8RKXvNgttGkr2VPD0IWJCOaBr8ZxUG +Fm/pRFeBe6tX02RVKx4QFPqCnb76bkvR1cNeFsV5eEz0WNRYzena+lD6Oqh074tk +oC9Uwl7D0l7xq17HNqAqHdMIO/T/TMPYyb7vskHPL9g8EJSgU55Z2Cjx3IlbJCpA +204cbbak4h99kgAqb4O5jT3gDe03NzWXCeQVKmacahusqNxzABEBAAGJAR8EGAEK +AAkFAlRClxICGwwACgkQPE8pgYSADbJFTwf/d6XIv8/BxaP5TB12FxRXevOVenYe +xR6O0rXDKFkP54LHSh2uaJbjLHevF0tuiNLFWq9RPhVjC012OLdo+2ygEFwNfikd +1SMbUIkuZ6Nu2MvCdrpAwbcvLgeoe8bqf1B6EIb31/OxCmtHujpVw6cSAnpAVyYo +PjPtEpcNatIHbOna4KANxwv1Rmc6XDxWIB0RIlbdZDUhEdLovLLWGjm4J++Cnn2n +OFdZyyUxwYTjDCMWwsYrG2oPZ0Yle6fKEXX30E+dN9NSV1i+dJAYQi0am6augpg+ +LmFWxQ6JPmUJVDay9wo6g2D4KbJQybSh8lmqpenHnKD1m/gCGadPmMl6Rw== +=FKbO +-----END PGP PUBLIC KEY BLOCK-----` + +var secring = ` +-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: GnuPG/MacGPG2 v2.0.22 (Darwin) +Comment: GPGTools - https://gpgtools.org + +lQOYBFRClxIBCACjlm8e2mI5TmeigPuF4HJqNxc6AFLoCsE3MQ6VtdEVqidXZ06L +m7uIXYc3IfvAlID+1KrUJnO2IgLEMmXKSDI5aOch7VaeoXLKMt7yAX+N6DHaZl4l +eUGlfyIuBGD7FY2rv4hHo2wOmlq/chnNA4T7wb2XzeaAjvvoxcedMZ2npVimjwsl +MNDxSxYPlHR6lJgfYJHAxcWn7ZQJW2Kllv9jMQwzGqW4fxuKRhe20KStE/4+K9gL +GWv6OoE2gcGLoXliIMchHobY0GEvVx+YUv5jAItRSXq4ajYjFLtsWLz6FYtK9CoO +Va6T5EGqozKST/olW/FMmKLOTzpAilyoKB/HABEBAAEAB/wKvEBo68JJaiH2nJ9P +qas92YVZMD9Al2rBoU2zOR4nsqW9SybGQP89aOHgQNyBcV1xG79lh8Eii+MsQUsZ +IMQcV2GKV5sjyDWScQ8yHjNi5SuBs85sMs5s5XB2nkvyU6JF9J5QETicprgw2x84 +AIn1buvvGTs4vD6/h7Hcri5fRimBvh+dcH/48nXPH56cZEPl/53tJt/lWwlfFBX1 +phZMIPoHT1kihEt//Hn4raw30R/bm0CJP/PtiyRkNeebzJsIJXtzG30B8YZb6c/h +TtobA4F4ZWtEEwotPBFtx4clS/+2amc+PY+ZGTKXjzvQChaz50gvtSUp9ns9X/G+ +T/vRBADC3dNGE2Ut8DRE2C/MQ7DdZdHdxaHJSMV+08xI/OSDOxp3ea1S2cbjniIG +cnuQ8ZXD4hWDKSZTGs2L4awdsL5eIhqACnxT3LXm0TBwBWDzE3CQZUQGc+2pFgDb +1Xc/By+OZgFCDlJhHuhK4Lf9EsH3HbV/Cmn8sDD+dKazLxUF1wQA1uiH8X/8dgcQ +uH/RSH2C7+Sr2B2Tpha9kngg4/cB31v3YaBV2t55zBvhSObxCM97gl6FadrEjJsw +FvN04DMWhlt2xWbLnt1v4suVo8V1Are4vqP8G/mWhJou2Ps/65nsFqStNHMA+xjQ +h8hAqY/9Mmu9Vm6WNRON0WCT3Snil5ED/0zUGI2qogw35Uzu448FrrYlh97kj3wu +RzOZB/mty2pVj9eJO0z6E3C6sYLvbxrd8TyFzs4fTP7WlwG5FMJu/I4cEBqUJ/rr ++ulSV/HH7zLpD6hWZbuRYhY8uskkVH50be4bb7MrXtoeDKrKfM4+BKf39QaBDNfI +jD0Perf+Ll0aRBm0LWFwcCAoYXBwIGNvbmZpZ3VyYXRpb24ga2V5KSA8YXBwQGV4 +YW1wbGUuY29tPokBNwQTAQoAIQUCVEKXEgIbAwULCQgHAwUVCgkICwUWAgMBAAIe +AQIXgAAKCRA8TymBhIANsjB1CACi4kqqWNSqAID7LmMswh5FQDEPkI/WA0h75xea +d11FVSdvtjWANY4Wob8RBjeZNT0TaCa0IAook+tLqA5xNbbvalOPV2zfr86BcGMh +Is900++PuVjOb7XaJPsEt5JwtzuLM+eDLIVhvMI7hQtgB39O8/AsWEW/E/JlVtHc +rsQ7LfcQYmNZVSnL71a8w4G+A6Sto89fvpjYh9/M4+aHqMhO/NLLp8Ylj5TlyiWK +HZlx5ufl2ejWMUot3wFhYADHPkhydmQV9IY1zzIpmB/75kvZqC4p92k7l8Ra82o+ +T75/dNy0HcgvgrfZQttxIM0WPEyVF5NjicSoakoggAAslhCNnQOYBFRClxIBCADJ +ltx4EgkFScH/EAmO6+mZb6+pcpjY/H97bX4wKUrQSDZjDAhoxsInKgqHwAo3QY26 +1eYrAyHvoTA2kRAaVrYWeGu3RxMmX5LTjFsXIW44ocTJK1XziUQympgIEayOUHt+ +XJaMGL8RKXvNgttGkr2VPD0IWJCOaBr8ZxUGFm/pRFeBe6tX02RVKx4QFPqCnb76 +bkvR1cNeFsV5eEz0WNRYzena+lD6Oqh074tkoC9Uwl7D0l7xq17HNqAqHdMIO/T/ +TMPYyb7vskHPL9g8EJSgU55Z2Cjx3IlbJCpA204cbbak4h99kgAqb4O5jT3gDe03 +NzWXCeQVKmacahusqNxzABEBAAEAB/47pozhaLDLpEonz9aMOImckfxgPx00Y+7T +FpC27pkJLb0OLPLWEi5ESX/pMG21cQvfw8iCZMBneIJcOyuRJ6Rk3Mg+6OSlP7Wi +LI+NtiI31sJ0poKd+Dm6YZ1oEdbGG9GXEA2qMe5jxSsxoi2BYg2AOd1zeUV5JhwK +IPSLIxuFYeDV/erv0n73Lob/Xj7SzhwRNQUJuG9Ak+maha1oqHwTuzPox9e+kSkK ++VOhW+9oTukxsg8lCD351X/VvHeJgZkfTshLbQdAbMUlBQ00O7TyprFFLKcd0MNL +gdVz5vHson5NyEzxsCbnV0Hty5Am00r1hm3Y89/k9HmBr3f+IH6JBADK0ZN9m4Br +xpc2fou40/HBKBPk/5sJoOcHklBM7j4COYqloYaYliZRKmeWfH3gPhYW+EOqsZtv +BPZaS7RL0IU8GoC1GfIrHJ+4GwiZQm6URDvEVSWsWiaUkI+cnK1HX8zsWHq48tqF +yVSOZ05Lh3Id65s3mnXzF3/zzQLMmKm1OwQA/nLDZSMRdr/WWW2nFpf5QH0y9eI3 +VU/4/QSIBLFL5iAXOebHDseCr7/G/W6hn00VTQIUq3UKDi+gy9epm9aBrdNyF3Ey +PvuACFLduF4ZnPOeZ1YrBxCRPHnGf+3So2Kcl9c1+RzMJ/qY+lZCU6pMCgCkeAZP +iTGeuExKr9OrIikD/Au6yH+Oc2GEvorhoWcerEeXFvvx1S+9oJBKnJl9y6PRJacy +wkZ354RyD9AojMJliibaHdAdpGSrOL8NEYQGy/3YzW1sMS2GBw6yZJ/GPCRDVEaE +Nkbi/Aj3Shh2+w/jeYsUgrJkZY/UeoJt/mdUO1+loRoqTdlOOJLpPcyF6WzQQU+J +AR8EGAEKAAkFAlRClxICGwwACgkQPE8pgYSADbJFTwf/d6XIv8/BxaP5TB12FxRX +evOVenYexR6O0rXDKFkP54LHSh2uaJbjLHevF0tuiNLFWq9RPhVjC012OLdo+2yg +EFwNfikd1SMbUIkuZ6Nu2MvCdrpAwbcvLgeoe8bqf1B6EIb31/OxCmtHujpVw6cS +AnpAVyYoPjPtEpcNatIHbOna4KANxwv1Rmc6XDxWIB0RIlbdZDUhEdLovLLWGjm4 +J++Cnn2nOFdZyyUxwYTjDCMWwsYrG2oPZ0Yle6fKEXX30E+dN9NSV1i+dJAYQi0a +m6augpg+LmFWxQ6JPmUJVDay9wo6g2D4KbJQybSh8lmqpenHnKD1m/gCGadPmMl6 +Rw== +=RvPL +-----END PGP PRIVATE KEY BLOCK----- +` diff --git a/Godeps/_workspace/src/github.com/xordataexchange/crypt/encoding/secconf/secconf.go b/Godeps/_workspace/src/github.com/xordataexchange/crypt/encoding/secconf/secconf.go new file mode 100644 index 00000000..51c87462 --- /dev/null +++ b/Godeps/_workspace/src/github.com/xordataexchange/crypt/encoding/secconf/secconf.go @@ -0,0 +1,68 @@ +// Package secconf implements secconf encoding as specified in the following +// format: +// +// base64(gpg(gzip(data))) +// +package secconf + +import ( + "bytes" + "compress/gzip" + "encoding/base64" + "io" + "io/ioutil" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp" +) + +// Deocde decodes data using the secconf codec. +func Decode(data []byte, secertKeyring io.Reader) ([]byte, error) { + decoder := base64.NewDecoder(base64.StdEncoding, bytes.NewBuffer(data)) + entityList, err := openpgp.ReadArmoredKeyRing(secertKeyring) + if err != nil { + return nil, err + } + md, err := openpgp.ReadMessage(decoder, entityList, nil, nil) + if err != nil { + return nil, err + } + gzReader, err := gzip.NewReader(md.UnverifiedBody) + if err != nil { + return nil, err + } + defer gzReader.Close() + bytes, err := ioutil.ReadAll(gzReader) + if err != nil { + return nil, err + } + return bytes, nil +} + +// Encode encodes data to a base64 encoded using the secconf codec. +// data is encrypted with all public keys found in the supplied keyring. +func Encode(data []byte, keyring io.Reader) ([]byte, error) { + entityList, err := openpgp.ReadArmoredKeyRing(keyring) + if err != nil { + return nil, err + } + buffer := new(bytes.Buffer) + encoder := base64.NewEncoder(base64.StdEncoding, buffer) + pgpWriter, err := openpgp.Encrypt(encoder, entityList, nil, nil, nil) + if err != nil { + return nil, err + } + gzWriter := gzip.NewWriter(pgpWriter) + if _, err := gzWriter.Write(data); err != nil { + return nil, err + } + if err := gzWriter.Close(); err != nil { + return nil, err + } + if err := pgpWriter.Close(); err != nil { + return nil, err + } + if err := encoder.Close(); err != nil { + return nil, err + } + return buffer.Bytes(), nil +} diff --git a/Godeps/_workspace/src/github.com/xordataexchange/crypt/encoding/secconf/secconf_test.go b/Godeps/_workspace/src/github.com/xordataexchange/crypt/encoding/secconf/secconf_test.go new file mode 100644 index 00000000..2562f5e9 --- /dev/null +++ b/Godeps/_workspace/src/github.com/xordataexchange/crypt/encoding/secconf/secconf_test.go @@ -0,0 +1,28 @@ +package secconf + +import ( + "bytes" + "testing" +) + +var encodingTests = []struct { + in, out string +}{ + {"secret", "secret"}, +} + +func TestEncoding(t *testing.T) { + for _, tt := range encodingTests { + encoded, err := Encode([]byte(tt.in), bytes.NewBufferString(pubring)) + if err != nil { + t.Errorf(err.Error()) + } + decoded, err := Decode(encoded, bytes.NewBufferString(secring)) + if err != nil { + t.Errorf(err.Error()) + } + if tt.out != string(decoded) { + t.Errorf("want %s, got %s", tt.out, decoded) + } + } +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/cast5/cast5.go b/Godeps/_workspace/src/golang.org/x/crypto/cast5/cast5.go new file mode 100644 index 00000000..8c1b299b --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/cast5/cast5.go @@ -0,0 +1,526 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common +// OpenPGP cipher. +package cast5 + +import "errors" + +const BlockSize = 8 +const KeySize = 16 + +type Cipher struct { + masking [16]uint32 + rotate [16]uint8 +} + +func NewCipher(key []byte) (c *Cipher, err error) { + if len(key) != KeySize { + return nil, errors.New("CAST5: keys must be 16 bytes") + } + + c = new(Cipher) + c.keySchedule(key) + return +} + +func (c *Cipher) BlockSize() int { + return BlockSize +} + +func (c *Cipher) Encrypt(dst, src []byte) { + l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) + r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) + + l, r = r, l^f1(r, c.masking[0], c.rotate[0]) + l, r = r, l^f2(r, c.masking[1], c.rotate[1]) + l, r = r, l^f3(r, c.masking[2], c.rotate[2]) + l, r = r, l^f1(r, c.masking[3], c.rotate[3]) + + l, r = r, l^f2(r, c.masking[4], c.rotate[4]) + l, r = r, l^f3(r, c.masking[5], c.rotate[5]) + l, r = r, l^f1(r, c.masking[6], c.rotate[6]) + l, r = r, l^f2(r, c.masking[7], c.rotate[7]) + + l, r = r, l^f3(r, c.masking[8], c.rotate[8]) + l, r = r, l^f1(r, c.masking[9], c.rotate[9]) + l, r = r, l^f2(r, c.masking[10], c.rotate[10]) + l, r = r, l^f3(r, c.masking[11], c.rotate[11]) + + l, r = r, l^f1(r, c.masking[12], c.rotate[12]) + l, r = r, l^f2(r, c.masking[13], c.rotate[13]) + l, r = r, l^f3(r, c.masking[14], c.rotate[14]) + l, r = r, l^f1(r, c.masking[15], c.rotate[15]) + + dst[0] = uint8(r >> 24) + dst[1] = uint8(r >> 16) + dst[2] = uint8(r >> 8) + dst[3] = uint8(r) + dst[4] = uint8(l >> 24) + dst[5] = uint8(l >> 16) + dst[6] = uint8(l >> 8) + dst[7] = uint8(l) +} + +func (c *Cipher) Decrypt(dst, src []byte) { + l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) + r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) + + l, r = r, l^f1(r, c.masking[15], c.rotate[15]) + l, r = r, l^f3(r, c.masking[14], c.rotate[14]) + l, r = r, l^f2(r, c.masking[13], c.rotate[13]) + l, r = r, l^f1(r, c.masking[12], c.rotate[12]) + + l, r = r, l^f3(r, c.masking[11], c.rotate[11]) + l, r = r, l^f2(r, c.masking[10], c.rotate[10]) + l, r = r, l^f1(r, c.masking[9], c.rotate[9]) + l, r = r, l^f3(r, c.masking[8], c.rotate[8]) + + l, r = r, l^f2(r, c.masking[7], c.rotate[7]) + l, r = r, l^f1(r, c.masking[6], c.rotate[6]) + l, r = r, l^f3(r, c.masking[5], c.rotate[5]) + l, r = r, l^f2(r, c.masking[4], c.rotate[4]) + + l, r = r, l^f1(r, c.masking[3], c.rotate[3]) + l, r = r, l^f3(r, c.masking[2], c.rotate[2]) + l, r = r, l^f2(r, c.masking[1], c.rotate[1]) + l, r = r, l^f1(r, c.masking[0], c.rotate[0]) + + dst[0] = uint8(r >> 24) + dst[1] = uint8(r >> 16) + dst[2] = uint8(r >> 8) + dst[3] = uint8(r) + dst[4] = uint8(l >> 24) + dst[5] = uint8(l >> 16) + dst[6] = uint8(l >> 8) + dst[7] = uint8(l) +} + +type keyScheduleA [4][7]uint8 +type keyScheduleB [4][5]uint8 + +// keyScheduleRound contains the magic values for a round of the key schedule. +// The keyScheduleA deals with the lines like: +// z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8] +// Conceptually, both x and z are in the same array, x first. The first +// element describes which word of this array gets written to and the +// second, which word gets read. So, for the line above, it's "4, 0", because +// it's writing to the first word of z, which, being after x, is word 4, and +// reading from the first word of x: word 0. +// +// Next are the indexes into the S-boxes. Now the array is treated as bytes. So +// "xD" is 0xd. The first byte of z is written as "16 + 0", just to be clear +// that it's z that we're indexing. +// +// keyScheduleB deals with lines like: +// K1 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2] +// "K1" is ignored because key words are always written in order. So the five +// elements are the S-box indexes. They use the same form as in keyScheduleA, +// above. + +type keyScheduleRound struct{} +type keySchedule []keyScheduleRound + +var schedule = []struct { + a keyScheduleA + b keyScheduleB +}{ + { + keyScheduleA{ + {4, 0, 0xd, 0xf, 0xc, 0xe, 0x8}, + {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa}, + {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9}, + {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb}, + }, + keyScheduleB{ + {16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2}, + {16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6}, + {16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9}, + {16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc}, + }, + }, + { + keyScheduleA{ + {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0}, + {1, 4, 0, 2, 1, 3, 16 + 2}, + {2, 5, 7, 6, 5, 4, 16 + 1}, + {3, 7, 0xa, 9, 0xb, 8, 16 + 3}, + }, + keyScheduleB{ + {3, 2, 0xc, 0xd, 8}, + {1, 0, 0xe, 0xf, 0xd}, + {7, 6, 8, 9, 3}, + {5, 4, 0xa, 0xb, 7}, + }, + }, + { + keyScheduleA{ + {4, 0, 0xd, 0xf, 0xc, 0xe, 8}, + {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa}, + {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9}, + {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb}, + }, + keyScheduleB{ + {16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9}, + {16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc}, + {16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2}, + {16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6}, + }, + }, + { + keyScheduleA{ + {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0}, + {1, 4, 0, 2, 1, 3, 16 + 2}, + {2, 5, 7, 6, 5, 4, 16 + 1}, + {3, 7, 0xa, 9, 0xb, 8, 16 + 3}, + }, + keyScheduleB{ + {8, 9, 7, 6, 3}, + {0xa, 0xb, 5, 4, 7}, + {0xc, 0xd, 3, 2, 8}, + {0xe, 0xf, 1, 0, 0xd}, + }, + }, +} + +func (c *Cipher) keySchedule(in []byte) { + var t [8]uint32 + var k [32]uint32 + + for i := 0; i < 4; i++ { + j := i * 4 + t[i] = uint32(in[j])<<24 | uint32(in[j+1])<<16 | uint32(in[j+2])<<8 | uint32(in[j+3]) + } + + x := []byte{6, 7, 4, 5} + ki := 0 + + for half := 0; half < 2; half++ { + for _, round := range schedule { + for j := 0; j < 4; j++ { + var a [7]uint8 + copy(a[:], round.a[j][:]) + w := t[a[1]] + w ^= sBox[4][(t[a[2]>>2]>>(24-8*(a[2]&3)))&0xff] + w ^= sBox[5][(t[a[3]>>2]>>(24-8*(a[3]&3)))&0xff] + w ^= sBox[6][(t[a[4]>>2]>>(24-8*(a[4]&3)))&0xff] + w ^= sBox[7][(t[a[5]>>2]>>(24-8*(a[5]&3)))&0xff] + w ^= sBox[x[j]][(t[a[6]>>2]>>(24-8*(a[6]&3)))&0xff] + t[a[0]] = w + } + + for j := 0; j < 4; j++ { + var b [5]uint8 + copy(b[:], round.b[j][:]) + w := sBox[4][(t[b[0]>>2]>>(24-8*(b[0]&3)))&0xff] + w ^= sBox[5][(t[b[1]>>2]>>(24-8*(b[1]&3)))&0xff] + w ^= sBox[6][(t[b[2]>>2]>>(24-8*(b[2]&3)))&0xff] + w ^= sBox[7][(t[b[3]>>2]>>(24-8*(b[3]&3)))&0xff] + w ^= sBox[4+j][(t[b[4]>>2]>>(24-8*(b[4]&3)))&0xff] + k[ki] = w + ki++ + } + } + } + + for i := 0; i < 16; i++ { + c.masking[i] = k[i] + c.rotate[i] = uint8(k[16+i] & 0x1f) + } +} + +// These are the three 'f' functions. See RFC 2144, section 2.2. +func f1(d, m uint32, r uint8) uint32 { + t := m + d + I := (t << r) | (t >> (32 - r)) + return ((sBox[0][I>>24] ^ sBox[1][(I>>16)&0xff]) - sBox[2][(I>>8)&0xff]) + sBox[3][I&0xff] +} + +func f2(d, m uint32, r uint8) uint32 { + t := m ^ d + I := (t << r) | (t >> (32 - r)) + return ((sBox[0][I>>24] - sBox[1][(I>>16)&0xff]) + sBox[2][(I>>8)&0xff]) ^ sBox[3][I&0xff] +} + +func f3(d, m uint32, r uint8) uint32 { + t := m - d + I := (t << r) | (t >> (32 - r)) + return ((sBox[0][I>>24] + sBox[1][(I>>16)&0xff]) ^ sBox[2][(I>>8)&0xff]) - sBox[3][I&0xff] +} + +var sBox = [8][256]uint32{ + { + 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, + 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, + 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, + 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, + 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, + 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, + 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, + 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, + 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, + 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, + 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, + 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, + 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, + 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, + 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, + 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, + 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, + 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, + 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, + 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, + 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, + 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, + 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, + 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, + 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, + 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, + 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, + 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, + 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, + 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, + 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, + 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf, + }, + { + 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, + 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, + 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, + 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, + 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, + 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, + 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, + 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, + 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, + 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, + 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, + 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, + 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, + 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, + 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, + 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, + 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, + 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, + 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, + 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, + 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, + 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, + 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, + 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, + 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, + 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, + 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, + 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, + 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, + 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, + 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, + 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1, + }, + { + 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, + 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, + 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, + 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, + 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, + 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, + 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, + 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, + 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, + 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, + 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, + 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, + 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, + 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, + 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, + 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, + 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, + 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, + 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, + 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, + 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, + 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, + 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, + 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, + 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, + 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, + 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, + 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, + 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, + 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, + 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, + 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783, + }, + { + 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, + 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, + 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, + 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, + 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, + 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, + 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, + 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, + 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, + 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, + 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, + 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, + 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, + 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, + 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, + 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, + 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, + 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, + 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, + 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, + 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, + 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, + 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, + 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, + 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, + 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, + 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, + 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, + 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, + 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, + 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, + 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2, + }, + { + 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, + 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, + 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, + 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, + 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, + 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, + 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, + 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, + 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, + 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, + 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, + 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, + 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, + 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, + 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, + 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, + 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, + 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, + 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, + 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, + 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, + 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, + 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, + 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, + 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, + 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, + 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, + 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, + 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, + 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, + 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, + 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4, + }, + { + 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, + 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, + 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, + 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, + 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, + 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, + 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, + 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, + 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, + 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, + 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, + 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, + 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, + 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, + 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, + 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, + 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, + 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, + 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, + 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, + 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, + 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, + 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, + 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, + 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, + 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, + 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, + 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, + 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, + 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, + 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, + 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f, + }, + { + 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, + 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, + 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, + 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, + 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, + 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, + 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, + 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, + 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, + 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, + 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, + 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, + 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, + 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, + 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, + 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, + 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, + 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, + 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, + 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, + 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, + 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, + 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, + 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, + 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, + 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, + 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, + 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, + 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, + 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, + 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, + 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3, + }, + { + 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, + 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, + 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, + 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, + 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, + 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, + 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, + 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, + 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, + 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, + 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, + 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, + 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, + 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, + 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, + 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, + 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, + 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, + 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, + 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, + 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, + 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, + 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, + 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, + 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, + 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, + 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, + 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, + 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, + 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, + 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, + 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e, + }, +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/cast5/cast5_test.go b/Godeps/_workspace/src/golang.org/x/crypto/cast5/cast5_test.go new file mode 100644 index 00000000..778b272a --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/cast5/cast5_test.go @@ -0,0 +1,106 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cast5 + +import ( + "bytes" + "encoding/hex" + "testing" +) + +// This test vector is taken from RFC 2144, App B.1. +// Since the other two test vectors are for reduced-round variants, we can't +// use them. +var basicTests = []struct { + key, plainText, cipherText string +}{ + { + "0123456712345678234567893456789a", + "0123456789abcdef", + "238b4fe5847e44b2", + }, +} + +func TestBasic(t *testing.T) { + for i, test := range basicTests { + key, _ := hex.DecodeString(test.key) + plainText, _ := hex.DecodeString(test.plainText) + expected, _ := hex.DecodeString(test.cipherText) + + c, err := NewCipher(key) + if err != nil { + t.Errorf("#%d: failed to create Cipher: %s", i, err) + continue + } + var cipherText [BlockSize]byte + c.Encrypt(cipherText[:], plainText) + if !bytes.Equal(cipherText[:], expected) { + t.Errorf("#%d: got:%x want:%x", i, cipherText, expected) + } + + var plainTextAgain [BlockSize]byte + c.Decrypt(plainTextAgain[:], cipherText[:]) + if !bytes.Equal(plainTextAgain[:], plainText) { + t.Errorf("#%d: got:%x want:%x", i, plainTextAgain, plainText) + } + } +} + +// TestFull performs the test specified in RFC 2144, App B.2. +// However, due to the length of time taken, it's disabled here and a more +// limited version is included, below. +func TestFull(t *testing.T) { + if testing.Short() { + // This is too slow for normal testing + return + } + + a, b := iterate(1000000) + + const expectedA = "eea9d0a249fd3ba6b3436fb89d6dca92" + const expectedB = "b2c95eb00c31ad7180ac05b8e83d696e" + + if hex.EncodeToString(a) != expectedA { + t.Errorf("a: got:%x want:%s", a, expectedA) + } + if hex.EncodeToString(b) != expectedB { + t.Errorf("b: got:%x want:%s", b, expectedB) + } +} + +func iterate(iterations int) ([]byte, []byte) { + const initValueHex = "0123456712345678234567893456789a" + + initValue, _ := hex.DecodeString(initValueHex) + + var a, b [16]byte + copy(a[:], initValue) + copy(b[:], initValue) + + for i := 0; i < iterations; i++ { + c, _ := NewCipher(b[:]) + c.Encrypt(a[:8], a[:8]) + c.Encrypt(a[8:], a[8:]) + c, _ = NewCipher(a[:]) + c.Encrypt(b[:8], b[:8]) + c.Encrypt(b[8:], b[8:]) + } + + return a[:], b[:] +} + +func TestLimited(t *testing.T) { + a, b := iterate(1000) + + const expectedA = "23f73b14b02a2ad7dfb9f2c35644798d" + const expectedB = "e5bf37eff14c456a40b21ce369370a9f" + + if hex.EncodeToString(a) != expectedA { + t.Errorf("a: got:%x want:%s", a, expectedA) + } + if hex.EncodeToString(b) != expectedB { + t.Errorf("b: got:%x want:%s", b, expectedB) + } +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/armor/armor.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/armor/armor.go new file mode 100644 index 00000000..f61c888a --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/armor/armor.go @@ -0,0 +1,219 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is +// very similar to PEM except that it has an additional CRC checksum. +package armor + +import ( + "bufio" + "bytes" + "encoding/base64" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "io" +) + +// A Block represents an OpenPGP armored structure. +// +// The encoded form is: +// -----BEGIN Type----- +// Headers +// +// base64-encoded Bytes +// '=' base64 encoded checksum +// -----END Type----- +// where Headers is a possibly empty sequence of Key: Value lines. +// +// Since the armored data can be very large, this package presents a streaming +// interface. +type Block struct { + Type string // The type, taken from the preamble (i.e. "PGP SIGNATURE"). + Header map[string]string // Optional headers. + Body io.Reader // A Reader from which the contents can be read + lReader lineReader + oReader openpgpReader +} + +var ArmorCorrupt error = errors.StructuralError("armor invalid") + +const crc24Init = 0xb704ce +const crc24Poly = 0x1864cfb +const crc24Mask = 0xffffff + +// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1 +func crc24(crc uint32, d []byte) uint32 { + for _, b := range d { + crc ^= uint32(b) << 16 + for i := 0; i < 8; i++ { + crc <<= 1 + if crc&0x1000000 != 0 { + crc ^= crc24Poly + } + } + } + return crc +} + +var armorStart = []byte("-----BEGIN ") +var armorEnd = []byte("-----END ") +var armorEndOfLine = []byte("-----") + +// lineReader wraps a line based reader. It watches for the end of an armor +// block and records the expected CRC value. +type lineReader struct { + in *bufio.Reader + buf []byte + eof bool + crc uint32 +} + +func (l *lineReader) Read(p []byte) (n int, err error) { + if l.eof { + return 0, io.EOF + } + + if len(l.buf) > 0 { + n = copy(p, l.buf) + l.buf = l.buf[n:] + return + } + + line, isPrefix, err := l.in.ReadLine() + if err != nil { + return + } + if isPrefix { + return 0, ArmorCorrupt + } + + if len(line) == 5 && line[0] == '=' { + // This is the checksum line + var expectedBytes [3]byte + var m int + m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:]) + if m != 3 || err != nil { + return + } + l.crc = uint32(expectedBytes[0])<<16 | + uint32(expectedBytes[1])<<8 | + uint32(expectedBytes[2]) + + line, _, err = l.in.ReadLine() + if err != nil && err != io.EOF { + return + } + if !bytes.HasPrefix(line, armorEnd) { + return 0, ArmorCorrupt + } + + l.eof = true + return 0, io.EOF + } + + if len(line) > 96 { + return 0, ArmorCorrupt + } + + n = copy(p, line) + bytesToSave := len(line) - n + if bytesToSave > 0 { + if cap(l.buf) < bytesToSave { + l.buf = make([]byte, 0, bytesToSave) + } + l.buf = l.buf[0:bytesToSave] + copy(l.buf, line[n:]) + } + + return +} + +// openpgpReader passes Read calls to the underlying base64 decoder, but keeps +// a running CRC of the resulting data and checks the CRC against the value +// found by the lineReader at EOF. +type openpgpReader struct { + lReader *lineReader + b64Reader io.Reader + currentCRC uint32 +} + +func (r *openpgpReader) Read(p []byte) (n int, err error) { + n, err = r.b64Reader.Read(p) + r.currentCRC = crc24(r.currentCRC, p[:n]) + + if err == io.EOF { + if r.lReader.crc != uint32(r.currentCRC&crc24Mask) { + return 0, ArmorCorrupt + } + } + + return +} + +// Decode reads a PGP armored block from the given Reader. It will ignore +// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The +// given Reader is not usable after calling this function: an arbitrary amount +// of data may have been read past the end of the block. +func Decode(in io.Reader) (p *Block, err error) { + r := bufio.NewReaderSize(in, 100) + var line []byte + ignoreNext := false + +TryNextBlock: + p = nil + + // Skip leading garbage + for { + ignoreThis := ignoreNext + line, ignoreNext, err = r.ReadLine() + if err != nil { + return + } + if ignoreNext || ignoreThis { + continue + } + line = bytes.TrimSpace(line) + if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) { + break + } + } + + p = new(Block) + p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)]) + p.Header = make(map[string]string) + nextIsContinuation := false + var lastKey string + + // Read headers + for { + isContinuation := nextIsContinuation + line, nextIsContinuation, err = r.ReadLine() + if err != nil { + p = nil + return + } + if isContinuation { + p.Header[lastKey] += string(line) + continue + } + line = bytes.TrimSpace(line) + if len(line) == 0 { + break + } + + i := bytes.Index(line, []byte(": ")) + if i == -1 { + goto TryNextBlock + } + lastKey = string(line[:i]) + p.Header[lastKey] = string(line[i+2:]) + } + + p.lReader.in = r + p.oReader.currentCRC = crc24Init + p.oReader.lReader = &p.lReader + p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader) + p.Body = &p.oReader + + return +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/armor/armor_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/armor/armor_test.go new file mode 100644 index 00000000..9334e94e --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/armor/armor_test.go @@ -0,0 +1,95 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package armor + +import ( + "bytes" + "hash/adler32" + "io/ioutil" + "testing" +) + +func TestDecodeEncode(t *testing.T) { + buf := bytes.NewBuffer([]byte(armorExample1)) + result, err := Decode(buf) + if err != nil { + t.Error(err) + } + expectedType := "PGP SIGNATURE" + if result.Type != expectedType { + t.Errorf("result.Type: got:%s want:%s", result.Type, expectedType) + } + if len(result.Header) != 1 { + t.Errorf("len(result.Header): got:%d want:1", len(result.Header)) + } + v, ok := result.Header["Version"] + if !ok || v != "GnuPG v1.4.10 (GNU/Linux)" { + t.Errorf("result.Header: got:%#v", result.Header) + } + + contents, err := ioutil.ReadAll(result.Body) + if err != nil { + t.Error(err) + } + + if adler32.Checksum(contents) != 0x27b144be { + t.Errorf("contents: got: %x", contents) + } + + buf = bytes.NewBuffer(nil) + w, err := Encode(buf, result.Type, result.Header) + if err != nil { + t.Error(err) + } + _, err = w.Write(contents) + if err != nil { + t.Error(err) + } + w.Close() + + if !bytes.Equal(buf.Bytes(), []byte(armorExample1)) { + t.Errorf("got: %s\nwant: %s", string(buf.Bytes()), armorExample1) + } +} + +func TestLongHeader(t *testing.T) { + buf := bytes.NewBuffer([]byte(armorLongLine)) + result, err := Decode(buf) + if err != nil { + t.Error(err) + return + } + value, ok := result.Header["Version"] + if !ok { + t.Errorf("missing Version header") + } + if value != longValueExpected { + t.Errorf("got: %s want: %s", value, longValueExpected) + } +} + +const armorExample1 = `-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.10 (GNU/Linux) + +iJwEAAECAAYFAk1Fv/0ACgkQo01+GMIMMbsYTwQAiAw+QAaNfY6WBdplZ/uMAccm +4g+81QPmTSGHnetSb6WBiY13kVzK4HQiZH8JSkmmroMLuGeJwsRTEL4wbjRyUKEt +p1xwUZDECs234F1xiG5enc5SGlRtP7foLBz9lOsjx+LEcA4sTl5/2eZR9zyFZqWW +TxRjs+fJCIFuo71xb1g= +=/teI +-----END PGP SIGNATURE-----` + +const armorLongLine = `-----BEGIN PGP SIGNATURE----- +Version: 0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz + +iQEcBAABAgAGBQJMtFESAAoJEKsQXJGvOPsVj40H/1WW6jaMXv4BW+1ueDSMDwM8 +kx1fLOXbVM5/Kn5LStZNt1jWWnpxdz7eq3uiqeCQjmqUoRde3YbB2EMnnwRbAhpp +cacnAvy9ZQ78OTxUdNW1mhX5bS6q1MTEJnl+DcyigD70HG/yNNQD7sOPMdYQw0TA +byQBwmLwmTsuZsrYqB68QyLHI+DUugn+kX6Hd2WDB62DKa2suoIUIHQQCd/ofwB3 +WfCYInXQKKOSxu2YOg2Eb4kLNhSMc1i9uKUWAH+sdgJh7NBgdoE4MaNtBFkHXRvv +okWuf3+xA9ksp1npSY/mDvgHijmjvtpRDe6iUeqfCn8N9u9CBg8geANgaG8+QA4= +=wfQG +-----END PGP SIGNATURE-----` + +const longValueExpected = "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz" diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/armor/encode.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/armor/encode.go new file mode 100644 index 00000000..6f07582c --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/armor/encode.go @@ -0,0 +1,160 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package armor + +import ( + "encoding/base64" + "io" +) + +var armorHeaderSep = []byte(": ") +var blockEnd = []byte("\n=") +var newline = []byte("\n") +var armorEndOfLineOut = []byte("-----\n") + +// writeSlices writes its arguments to the given Writer. +func writeSlices(out io.Writer, slices ...[]byte) (err error) { + for _, s := range slices { + _, err = out.Write(s) + if err != nil { + return err + } + } + return +} + +// lineBreaker breaks data across several lines, all of the same byte length +// (except possibly the last). Lines are broken with a single '\n'. +type lineBreaker struct { + lineLength int + line []byte + used int + out io.Writer + haveWritten bool +} + +func newLineBreaker(out io.Writer, lineLength int) *lineBreaker { + return &lineBreaker{ + lineLength: lineLength, + line: make([]byte, lineLength), + used: 0, + out: out, + } +} + +func (l *lineBreaker) Write(b []byte) (n int, err error) { + n = len(b) + + if n == 0 { + return + } + + if l.used == 0 && l.haveWritten { + _, err = l.out.Write([]byte{'\n'}) + if err != nil { + return + } + } + + if l.used+len(b) < l.lineLength { + l.used += copy(l.line[l.used:], b) + return + } + + l.haveWritten = true + _, err = l.out.Write(l.line[0:l.used]) + if err != nil { + return + } + excess := l.lineLength - l.used + l.used = 0 + + _, err = l.out.Write(b[0:excess]) + if err != nil { + return + } + + _, err = l.Write(b[excess:]) + return +} + +func (l *lineBreaker) Close() (err error) { + if l.used > 0 { + _, err = l.out.Write(l.line[0:l.used]) + if err != nil { + return + } + } + + return +} + +// encoding keeps track of a running CRC24 over the data which has been written +// to it and outputs a OpenPGP checksum when closed, followed by an armor +// trailer. +// +// It's built into a stack of io.Writers: +// encoding -> base64 encoder -> lineBreaker -> out +type encoding struct { + out io.Writer + breaker *lineBreaker + b64 io.WriteCloser + crc uint32 + blockType []byte +} + +func (e *encoding) Write(data []byte) (n int, err error) { + e.crc = crc24(e.crc, data) + return e.b64.Write(data) +} + +func (e *encoding) Close() (err error) { + err = e.b64.Close() + if err != nil { + return + } + e.breaker.Close() + + var checksumBytes [3]byte + checksumBytes[0] = byte(e.crc >> 16) + checksumBytes[1] = byte(e.crc >> 8) + checksumBytes[2] = byte(e.crc) + + var b64ChecksumBytes [4]byte + base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:]) + + return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine) +} + +// Encode returns a WriteCloser which will encode the data written to it in +// OpenPGP armor. +func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) { + bType := []byte(blockType) + err = writeSlices(out, armorStart, bType, armorEndOfLineOut) + if err != nil { + return + } + + for k, v := range headers { + err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline) + if err != nil { + return + } + } + + _, err = out.Write(newline) + if err != nil { + return + } + + e := &encoding{ + out: out, + breaker: newLineBreaker(out, 64), + crc: crc24Init, + blockType: bType, + } + e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker) + return e, nil +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/canonical_text.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/canonical_text.go new file mode 100644 index 00000000..e601e389 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/canonical_text.go @@ -0,0 +1,59 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package openpgp + +import "hash" + +// NewCanonicalTextHash reformats text written to it into the canonical +// form and then applies the hash h. See RFC 4880, section 5.2.1. +func NewCanonicalTextHash(h hash.Hash) hash.Hash { + return &canonicalTextHash{h, 0} +} + +type canonicalTextHash struct { + h hash.Hash + s int +} + +var newline = []byte{'\r', '\n'} + +func (cth *canonicalTextHash) Write(buf []byte) (int, error) { + start := 0 + + for i, c := range buf { + switch cth.s { + case 0: + if c == '\r' { + cth.s = 1 + } else if c == '\n' { + cth.h.Write(buf[start:i]) + cth.h.Write(newline) + start = i + 1 + } + case 1: + cth.s = 0 + } + } + + cth.h.Write(buf[start:]) + return len(buf), nil +} + +func (cth *canonicalTextHash) Sum(in []byte) []byte { + return cth.h.Sum(in) +} + +func (cth *canonicalTextHash) Reset() { + cth.h.Reset() + cth.s = 0 +} + +func (cth *canonicalTextHash) Size() int { + return cth.h.Size() +} + +func (cth *canonicalTextHash) BlockSize() int { + return cth.h.BlockSize() +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/canonical_text_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/canonical_text_test.go new file mode 100644 index 00000000..8f3ba2a8 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/canonical_text_test.go @@ -0,0 +1,52 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package openpgp + +import ( + "bytes" + "testing" +) + +type recordingHash struct { + buf *bytes.Buffer +} + +func (r recordingHash) Write(b []byte) (n int, err error) { + return r.buf.Write(b) +} + +func (r recordingHash) Sum(in []byte) []byte { + return append(in, r.buf.Bytes()...) +} + +func (r recordingHash) Reset() { + panic("shouldn't be called") +} + +func (r recordingHash) Size() int { + panic("shouldn't be called") +} + +func (r recordingHash) BlockSize() int { + panic("shouldn't be called") +} + +func testCanonicalText(t *testing.T, input, expected string) { + r := recordingHash{bytes.NewBuffer(nil)} + c := NewCanonicalTextHash(r) + c.Write([]byte(input)) + result := c.Sum(nil) + if expected != string(result) { + t.Errorf("input: %x got: %x want: %x", input, result, expected) + } +} + +func TestCanonicalText(t *testing.T) { + testCanonicalText(t, "foo\n", "foo\r\n") + testCanonicalText(t, "foo", "foo") + testCanonicalText(t, "foo\r\n", "foo\r\n") + testCanonicalText(t, "foo\r\nbar", "foo\r\nbar") + testCanonicalText(t, "foo\r\nbar\n\n", "foo\r\nbar\r\n\r\n") +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/clearsign/clearsign.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/clearsign/clearsign.go new file mode 100644 index 00000000..c9686944 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/clearsign/clearsign.go @@ -0,0 +1,366 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package clearsign generates and processes OpenPGP, clear-signed data. See +// RFC 4880, section 7. +// +// Clearsigned messages are cryptographically signed, but the contents of the +// message are kept in plaintext so that it can be read without special tools. +package clearsign + +import ( + "bufio" + "bytes" + "crypto" + "hash" + "io" + "net/textproto" + "strconv" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/armor" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet" +) + +// A Block represents a clearsigned message. A signature on a Block can +// be checked by passing Bytes into openpgp.CheckDetachedSignature. +type Block struct { + Headers textproto.MIMEHeader // Optional message headers + Plaintext []byte // The original message text + Bytes []byte // The signed message + ArmoredSignature *armor.Block // The signature block +} + +// start is the marker which denotes the beginning of a clearsigned message. +var start = []byte("\n-----BEGIN PGP SIGNED MESSAGE-----") + +// dashEscape is prefixed to any lines that begin with a hypen so that they +// can't be confused with endText. +var dashEscape = []byte("- ") + +// endText is a marker which denotes the end of the message and the start of +// an armored signature. +var endText = []byte("-----BEGIN PGP SIGNATURE-----") + +// end is a marker which denotes the end of the armored signature. +var end = []byte("\n-----END PGP SIGNATURE-----") + +var crlf = []byte("\r\n") +var lf = byte('\n') + +// getLine returns the first \r\n or \n delineated line from the given byte +// array. The line does not include the \r\n or \n. The remainder of the byte +// array (also not including the new line bytes) is also returned and this will +// always be smaller than the original argument. +func getLine(data []byte) (line, rest []byte) { + i := bytes.Index(data, []byte{'\n'}) + var j int + if i < 0 { + i = len(data) + j = i + } else { + j = i + 1 + if i > 0 && data[i-1] == '\r' { + i-- + } + } + return data[0:i], data[j:] +} + +// Decode finds the first clearsigned message in data and returns it, as well +// as the suffix of data which remains after the message. +func Decode(data []byte) (b *Block, rest []byte) { + // start begins with a newline. However, at the very beginning of + // the byte array, we'll accept the start string without it. + rest = data + if bytes.HasPrefix(data, start[1:]) { + rest = rest[len(start)-1:] + } else if i := bytes.Index(data, start); i >= 0 { + rest = rest[i+len(start):] + } else { + return nil, data + } + + // Consume the start line. + _, rest = getLine(rest) + + var line []byte + b = &Block{ + Headers: make(textproto.MIMEHeader), + } + + // Next come a series of header lines. + for { + // This loop terminates because getLine's second result is + // always smaller than its argument. + if len(rest) == 0 { + return nil, data + } + // An empty line marks the end of the headers. + if line, rest = getLine(rest); len(line) == 0 { + break + } + + i := bytes.Index(line, []byte{':'}) + if i == -1 { + return nil, data + } + + key, val := line[0:i], line[i+1:] + key = bytes.TrimSpace(key) + val = bytes.TrimSpace(val) + b.Headers.Add(string(key), string(val)) + } + + firstLine := true + for { + start := rest + + line, rest = getLine(rest) + if bytes.Equal(line, endText) { + // Back up to the start of the line because armor expects to see the + // header line. + rest = start + break + } + + // The final CRLF isn't included in the hash so we don't write it until + // we've seen the next line. + if firstLine { + firstLine = false + } else { + b.Bytes = append(b.Bytes, crlf...) + } + + if bytes.HasPrefix(line, dashEscape) { + line = line[2:] + } + line = bytes.TrimRight(line, " \t") + b.Bytes = append(b.Bytes, line...) + + b.Plaintext = append(b.Plaintext, line...) + b.Plaintext = append(b.Plaintext, lf) + } + + // We want to find the extent of the armored data (including any newlines at + // the end). + i := bytes.Index(rest, end) + if i == -1 { + return nil, data + } + i += len(end) + for i < len(rest) && (rest[i] == '\r' || rest[i] == '\n') { + i++ + } + armored := rest[:i] + rest = rest[i:] + + var err error + b.ArmoredSignature, err = armor.Decode(bytes.NewBuffer(armored)) + if err != nil { + return nil, data + } + + return b, rest +} + +// A dashEscaper is an io.WriteCloser which processes the body of a clear-signed +// message. The clear-signed message is written to buffered and a hash, suitable +// for signing, is maintained in h. +// +// When closed, an armored signature is created and written to complete the +// message. +type dashEscaper struct { + buffered *bufio.Writer + h hash.Hash + hashType crypto.Hash + + atBeginningOfLine bool + isFirstLine bool + + whitespace []byte + byteBuf []byte // a one byte buffer to save allocations + + privateKey *packet.PrivateKey + config *packet.Config +} + +func (d *dashEscaper) Write(data []byte) (n int, err error) { + for _, b := range data { + d.byteBuf[0] = b + + if d.atBeginningOfLine { + // The final CRLF isn't included in the hash so we have to wait + // until this point (the start of the next line) before writing it. + if !d.isFirstLine { + d.h.Write(crlf) + } + d.isFirstLine = false + + // At the beginning of a line, hyphens have to be escaped. + if b == '-' { + // The signature isn't calculated over the dash-escaped text so + // the escape is only written to buffered. + if _, err = d.buffered.Write(dashEscape); err != nil { + return + } + d.h.Write(d.byteBuf) + d.atBeginningOfLine = false + } else if b == '\n' { + // Nothing to do because we dely writing CRLF to the hash. + } else { + d.h.Write(d.byteBuf) + d.atBeginningOfLine = false + } + if err = d.buffered.WriteByte(b); err != nil { + return + } + } else { + // Any whitespace at the end of the line has to be removed so we + // buffer it until we find out whether there's more on this line. + if b == ' ' || b == '\t' || b == '\r' { + d.whitespace = append(d.whitespace, b) + } else if b == '\n' { + // We got a raw \n. Drop any trailing whitespace and write a + // CRLF. + d.whitespace = d.whitespace[:0] + // We dely writing CRLF to the hash until the start of the + // next line. + if err = d.buffered.WriteByte(b); err != nil { + return + } + d.atBeginningOfLine = true + } else { + // Any buffered whitespace wasn't at the end of the line so + // we need to write it out. + if len(d.whitespace) > 0 { + d.h.Write(d.whitespace) + if _, err = d.buffered.Write(d.whitespace); err != nil { + return + } + d.whitespace = d.whitespace[:0] + } + d.h.Write(d.byteBuf) + if err = d.buffered.WriteByte(b); err != nil { + return + } + } + } + } + + n = len(data) + return +} + +func (d *dashEscaper) Close() (err error) { + if !d.atBeginningOfLine { + if err = d.buffered.WriteByte(lf); err != nil { + return + } + } + sig := new(packet.Signature) + sig.SigType = packet.SigTypeText + sig.PubKeyAlgo = d.privateKey.PubKeyAlgo + sig.Hash = d.hashType + sig.CreationTime = d.config.Now() + sig.IssuerKeyId = &d.privateKey.KeyId + + if err = sig.Sign(d.h, d.privateKey, d.config); err != nil { + return + } + + out, err := armor.Encode(d.buffered, "PGP SIGNATURE", nil) + if err != nil { + return + } + + if err = sig.Serialize(out); err != nil { + return + } + if err = out.Close(); err != nil { + return + } + if err = d.buffered.Flush(); err != nil { + return + } + return +} + +// Encode returns a WriteCloser which will clear-sign a message with privateKey +// and write it to w. If config is nil, sensible defaults are used. +func Encode(w io.Writer, privateKey *packet.PrivateKey, config *packet.Config) (plaintext io.WriteCloser, err error) { + if privateKey.Encrypted { + return nil, errors.InvalidArgumentError("signing key is encrypted") + } + + hashType := config.Hash() + name := nameOfHash(hashType) + if len(name) == 0 { + return nil, errors.UnsupportedError("unknown hash type: " + strconv.Itoa(int(hashType))) + } + + if !hashType.Available() { + return nil, errors.UnsupportedError("unsupported hash type: " + strconv.Itoa(int(hashType))) + } + h := hashType.New() + + buffered := bufio.NewWriter(w) + // start has a \n at the beginning that we don't want here. + if _, err = buffered.Write(start[1:]); err != nil { + return + } + if err = buffered.WriteByte(lf); err != nil { + return + } + if _, err = buffered.WriteString("Hash: "); err != nil { + return + } + if _, err = buffered.WriteString(name); err != nil { + return + } + if err = buffered.WriteByte(lf); err != nil { + return + } + if err = buffered.WriteByte(lf); err != nil { + return + } + + plaintext = &dashEscaper{ + buffered: buffered, + h: h, + hashType: hashType, + + atBeginningOfLine: true, + isFirstLine: true, + + byteBuf: make([]byte, 1), + + privateKey: privateKey, + config: config, + } + + return +} + +// nameOfHash returns the OpenPGP name for the given hash, or the empty string +// if the name isn't known. See RFC 4880, section 9.4. +func nameOfHash(h crypto.Hash) string { + switch h { + case crypto.MD5: + return "MD5" + case crypto.SHA1: + return "SHA1" + case crypto.RIPEMD160: + return "RIPEMD160" + case crypto.SHA224: + return "SHA224" + case crypto.SHA256: + return "SHA256" + case crypto.SHA384: + return "SHA384" + case crypto.SHA512: + return "SHA512" + } + return "" +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go new file mode 100644 index 00000000..818aa0fd --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go @@ -0,0 +1,187 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package clearsign + +import ( + "bytes" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp" + "testing" +) + +func testParse(t *testing.T, input []byte, expected, expectedPlaintext string) { + b, rest := Decode(input) + if b == nil { + t.Fatal("failed to decode clearsign message") + } + if !bytes.Equal(rest, []byte("trailing")) { + t.Errorf("unexpected remaining bytes returned: %s", string(rest)) + } + if b.ArmoredSignature.Type != "PGP SIGNATURE" { + t.Errorf("bad armor type, got:%s, want:PGP SIGNATURE", b.ArmoredSignature.Type) + } + if !bytes.Equal(b.Bytes, []byte(expected)) { + t.Errorf("bad body, got:%x want:%x", b.Bytes, expected) + } + + if !bytes.Equal(b.Plaintext, []byte(expectedPlaintext)) { + t.Errorf("bad plaintext, got:%x want:%x", b.Plaintext, expectedPlaintext) + } + + keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey)) + if err != nil { + t.Errorf("failed to parse public key: %s", err) + } + + if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil { + t.Errorf("failed to check signature: %s", err) + } +} + +func TestParse(t *testing.T) { + testParse(t, clearsignInput, "Hello world\r\nline 2", "Hello world\nline 2\n") + testParse(t, clearsignInput2, "\r\n\r\n(This message has a couple of blank lines at the start and end.)\r\n\r\n", "\n\n(This message has a couple of blank lines at the start and end.)\n\n\n") +} + +func TestParseWithNoNewlineAtEnd(t *testing.T) { + input := clearsignInput + input = input[:len(input)-len("trailing")-1] + b, rest := Decode(input) + if b == nil { + t.Fatal("failed to decode clearsign message") + } + if len(rest) > 0 { + t.Errorf("unexpected remaining bytes returned: %s", string(rest)) + } +} + +var signingTests = []struct { + in, signed, plaintext string +}{ + {"", "", ""}, + {"a", "a", "a\n"}, + {"a\n", "a", "a\n"}, + {"-a\n", "-a", "-a\n"}, + {"--a\nb", "--a\r\nb", "--a\nb\n"}, +} + +func TestSigning(t *testing.T) { + keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey)) + if err != nil { + t.Errorf("failed to parse public key: %s", err) + } + + for i, test := range signingTests { + var buf bytes.Buffer + + plaintext, err := Encode(&buf, keyring[0].PrivateKey, nil) + if err != nil { + t.Errorf("#%d: error from Encode: %s", i, err) + continue + } + if _, err := plaintext.Write([]byte(test.in)); err != nil { + t.Errorf("#%d: error from Write: %s", i, err) + continue + } + if err := plaintext.Close(); err != nil { + t.Fatalf("#%d: error from Close: %s", i, err) + continue + } + + b, _ := Decode(buf.Bytes()) + if b == nil { + t.Errorf("#%d: failed to decode clearsign message", i) + continue + } + if !bytes.Equal(b.Bytes, []byte(test.signed)) { + t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Bytes, test.signed) + continue + } + if !bytes.Equal(b.Plaintext, []byte(test.plaintext)) { + t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Plaintext, test.plaintext) + continue + } + + if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil { + t.Errorf("#%d: failed to check signature: %s", i, err) + } + } +} + +var clearsignInput = []byte(` +;lasjlkfdsa + +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +Hello world +line 2 +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.10 (GNU/Linux) + +iJwEAQECAAYFAk8kMuEACgkQO9o98PRieSpMsAQAhmY/vwmNpflrPgmfWsYhk5O8 +pjnBUzZwqTDoDeINjZEoPDSpQAHGhjFjgaDx/Gj4fAl0dM4D0wuUEBb6QOrwflog +2A2k9kfSOMOtk0IH/H5VuFN1Mie9L/erYXjTQIptv9t9J7NoRBMU0QOOaFU0JaO9 +MyTpno24AjIAGb+mH1U= +=hIJ6 +-----END PGP SIGNATURE----- +trailing`) + +var clearsignInput2 = []byte(` +asdlfkjasdlkfjsadf + +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA256 + + + +(This message has a couple of blank lines at the start and end.) + + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.11 (GNU/Linux) + +iJwEAQEIAAYFAlPpSREACgkQO9o98PRieSpZTAP+M8QUoCt/7Rf3YbXPcdzIL32v +pt1I+cMNeopzfLy0u4ioEFi8s5VkwpL1AFmirvgViCwlf82inoRxzZRiW05JQ5LI +ESEzeCoy2LIdRCQ2hcrG8pIUPzUO4TqO5D/dMbdHwNH4h5nNmGJUAEG6FpURlPm+ +qZg6BaTvOxepqOxnhVU= +=e+C6 +-----END PGP SIGNATURE----- + +trailing`) + +var signingKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: GnuPG v1.4.10 (GNU/Linux) + +lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp +idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn +vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB +AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X +0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL +IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk +VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn +gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9 +TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx +q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz +dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA +CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1 +ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+ +eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid +AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV +bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK +/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA +A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX +TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc +lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6 +rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN +oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8 +QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU +nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC +AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp +BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad +AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL +VrM0m72/jnpKo04= +=zNCn +-----END PGP PRIVATE KEY BLOCK----- +` diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/elgamal/elgamal.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/elgamal/elgamal.go new file mode 100644 index 00000000..a553bdee --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/elgamal/elgamal.go @@ -0,0 +1,122 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package elgamal implements ElGamal encryption, suitable for OpenPGP, +// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on +// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31, +// n. 4, 1985, pp. 469-472. +// +// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it +// unsuitable for other protocols. RSA should be used in preference in any +// case. +package elgamal + +import ( + "crypto/rand" + "crypto/subtle" + "errors" + "io" + "math/big" +) + +// PublicKey represents an ElGamal public key. +type PublicKey struct { + G, P, Y *big.Int +} + +// PrivateKey represents an ElGamal private key. +type PrivateKey struct { + PublicKey + X *big.Int +} + +// Encrypt encrypts the given message to the given public key. The result is a +// pair of integers. Errors can result from reading random, or because msg is +// too large to be encrypted to the public key. +func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) { + pLen := (pub.P.BitLen() + 7) / 8 + if len(msg) > pLen-11 { + err = errors.New("elgamal: message too long") + return + } + + // EM = 0x02 || PS || 0x00 || M + em := make([]byte, pLen-1) + em[0] = 2 + ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):] + err = nonZeroRandomBytes(ps, random) + if err != nil { + return + } + em[len(em)-len(msg)-1] = 0 + copy(mm, msg) + + m := new(big.Int).SetBytes(em) + + k, err := rand.Int(random, pub.P) + if err != nil { + return + } + + c1 = new(big.Int).Exp(pub.G, k, pub.P) + s := new(big.Int).Exp(pub.Y, k, pub.P) + c2 = s.Mul(s, m) + c2.Mod(c2, pub.P) + + return +} + +// Decrypt takes two integers, resulting from an ElGamal encryption, and +// returns the plaintext of the message. An error can result only if the +// ciphertext is invalid. Users should keep in mind that this is a padding +// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can +// be used to break the cryptosystem. See ``Chosen Ciphertext Attacks +// Against Protocols Based on the RSA Encryption Standard PKCS #1'', Daniel +// Bleichenbacher, Advances in Cryptology (Crypto '98), +func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) { + s := new(big.Int).Exp(c1, priv.X, priv.P) + s.ModInverse(s, priv.P) + s.Mul(s, c2) + s.Mod(s, priv.P) + em := s.Bytes() + + firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2) + + // The remainder of the plaintext must be a string of non-zero random + // octets, followed by a 0, followed by the message. + // lookingForIndex: 1 iff we are still looking for the zero. + // index: the offset of the first zero byte. + var lookingForIndex, index int + lookingForIndex = 1 + + for i := 1; i < len(em); i++ { + equals0 := subtle.ConstantTimeByteEq(em[i], 0) + index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index) + lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex) + } + + if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 { + return nil, errors.New("elgamal: decryption error") + } + return em[index+1:], nil +} + +// nonZeroRandomBytes fills the given slice with non-zero random octets. +func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) { + _, err = io.ReadFull(rand, s) + if err != nil { + return + } + + for i := 0; i < len(s); i++ { + for s[i] == 0 { + _, err = io.ReadFull(rand, s[i:i+1]) + if err != nil { + return + } + } + } + + return +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go new file mode 100644 index 00000000..c4f99f5c --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go @@ -0,0 +1,49 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package elgamal + +import ( + "bytes" + "crypto/rand" + "math/big" + "testing" +) + +// This is the 1024-bit MODP group from RFC 5114, section 2.1: +const primeHex = "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371" + +const generatorHex = "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507FD6406CFF14266D31266FEA1E5C41564B777E690F5504F213160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28AD662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24855E6EEB22B3B2E5" + +func fromHex(hex string) *big.Int { + n, ok := new(big.Int).SetString(hex, 16) + if !ok { + panic("failed to parse hex number") + } + return n +} + +func TestEncryptDecrypt(t *testing.T) { + priv := &PrivateKey{ + PublicKey: PublicKey{ + G: fromHex(generatorHex), + P: fromHex(primeHex), + }, + X: fromHex("42"), + } + priv.Y = new(big.Int).Exp(priv.G, priv.X, priv.P) + + message := []byte("hello world") + c1, c2, err := Encrypt(rand.Reader, &priv.PublicKey, message) + if err != nil { + t.Errorf("error encrypting: %s", err) + } + message2, err := Decrypt(priv, c1, c2) + if err != nil { + t.Errorf("error decrypting: %s", err) + } + if !bytes.Equal(message2, message) { + t.Errorf("decryption failed, got: %x, want: %x", message2, message) + } +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors/errors.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors/errors.go new file mode 100644 index 00000000..6c4c2f17 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors/errors.go @@ -0,0 +1,72 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package errors contains common error types for the OpenPGP packages. +package errors + +import ( + "strconv" +) + +// A StructuralError is returned when OpenPGP data is found to be syntactically +// invalid. +type StructuralError string + +func (s StructuralError) Error() string { + return "openpgp: invalid data: " + string(s) +} + +// UnsupportedError indicates that, although the OpenPGP data is valid, it +// makes use of currently unimplemented features. +type UnsupportedError string + +func (s UnsupportedError) Error() string { + return "openpgp: unsupported feature: " + string(s) +} + +// InvalidArgumentError indicates that the caller is in error and passed an +// incorrect value. +type InvalidArgumentError string + +func (i InvalidArgumentError) Error() string { + return "openpgp: invalid argument: " + string(i) +} + +// SignatureError indicates that a syntactically valid signature failed to +// validate. +type SignatureError string + +func (b SignatureError) Error() string { + return "openpgp: invalid signature: " + string(b) +} + +type keyIncorrectError int + +func (ki keyIncorrectError) Error() string { + return "openpgp: incorrect key" +} + +var ErrKeyIncorrect error = keyIncorrectError(0) + +type unknownIssuerError int + +func (unknownIssuerError) Error() string { + return "openpgp: signature made by unknown entity" +} + +var ErrUnknownIssuer error = unknownIssuerError(0) + +type keyRevokedError int + +func (keyRevokedError) Error() string { + return "openpgp: signature made by revoked key" +} + +var ErrKeyRevoked error = keyRevokedError(0) + +type UnknownPacketTypeError uint8 + +func (upte UnknownPacketTypeError) Error() string { + return "openpgp: unknown packet type: " + strconv.Itoa(int(upte)) +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/keys.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/keys.go new file mode 100644 index 00000000..e4d844a2 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/keys.go @@ -0,0 +1,624 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package openpgp + +import ( + "crypto/rsa" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/armor" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet" + "io" + "time" +) + +// PublicKeyType is the armor type for a PGP public key. +var PublicKeyType = "PGP PUBLIC KEY BLOCK" + +// PrivateKeyType is the armor type for a PGP private key. +var PrivateKeyType = "PGP PRIVATE KEY BLOCK" + +// An Entity represents the components of an OpenPGP key: a primary public key +// (which must be a signing key), one or more identities claimed by that key, +// and zero or more subkeys, which may be encryption keys. +type Entity struct { + PrimaryKey *packet.PublicKey + PrivateKey *packet.PrivateKey + Identities map[string]*Identity // indexed by Identity.Name + Revocations []*packet.Signature + Subkeys []Subkey +} + +// An Identity represents an identity claimed by an Entity and zero or more +// assertions by other entities about that claim. +type Identity struct { + Name string // by convention, has the form "Full Name (comment) " + UserId *packet.UserId + SelfSignature *packet.Signature + Signatures []*packet.Signature +} + +// A Subkey is an additional public key in an Entity. Subkeys can be used for +// encryption. +type Subkey struct { + PublicKey *packet.PublicKey + PrivateKey *packet.PrivateKey + Sig *packet.Signature +} + +// A Key identifies a specific public key in an Entity. This is either the +// Entity's primary key or a subkey. +type Key struct { + Entity *Entity + PublicKey *packet.PublicKey + PrivateKey *packet.PrivateKey + SelfSignature *packet.Signature +} + +// A KeyRing provides access to public and private keys. +type KeyRing interface { + // KeysById returns the set of keys that have the given key id. + KeysById(id uint64) []Key + // KeysByIdAndUsage returns the set of keys with the given id + // that also meet the key usage given by requiredUsage. + // The requiredUsage is expressed as the bitwise-OR of + // packet.KeyFlag* values. + KeysByIdUsage(id uint64, requiredUsage byte) []Key + // DecryptionKeys returns all private keys that are valid for + // decryption. + DecryptionKeys() []Key +} + +// primaryIdentity returns the Identity marked as primary or the first identity +// if none are so marked. +func (e *Entity) primaryIdentity() *Identity { + var firstIdentity *Identity + for _, ident := range e.Identities { + if firstIdentity == nil { + firstIdentity = ident + } + if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { + return ident + } + } + return firstIdentity +} + +// encryptionKey returns the best candidate Key for encrypting a message to the +// given Entity. +func (e *Entity) encryptionKey(now time.Time) (Key, bool) { + candidateSubkey := -1 + + for i, subkey := range e.Subkeys { + if subkey.Sig.FlagsValid && + subkey.Sig.FlagEncryptCommunications && + subkey.PublicKey.PubKeyAlgo.CanEncrypt() && + !subkey.Sig.KeyExpired(now) { + candidateSubkey = i + break + } + } + + if candidateSubkey != -1 { + subkey := e.Subkeys[candidateSubkey] + return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true + } + + // If we don't have any candidate subkeys for encryption and + // the primary key doesn't have any usage metadata then we + // assume that the primary key is ok. Or, if the primary key is + // marked as ok to encrypt to, then we can obviously use it. + i := e.primaryIdentity() + if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications && + e.PrimaryKey.PubKeyAlgo.CanEncrypt() && + !i.SelfSignature.KeyExpired(now) { + return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true + } + + // This Entity appears to be signing only. + return Key{}, false +} + +// signingKey return the best candidate Key for signing a message with this +// Entity. +func (e *Entity) signingKey(now time.Time) (Key, bool) { + candidateSubkey := -1 + + for i, subkey := range e.Subkeys { + if subkey.Sig.FlagsValid && + subkey.Sig.FlagSign && + subkey.PublicKey.PubKeyAlgo.CanSign() && + !subkey.Sig.KeyExpired(now) { + candidateSubkey = i + break + } + } + + if candidateSubkey != -1 { + subkey := e.Subkeys[candidateSubkey] + return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true + } + + // If we have no candidate subkey then we assume that it's ok to sign + // with the primary key. + i := e.primaryIdentity() + if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign && + !i.SelfSignature.KeyExpired(now) { + return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true + } + + return Key{}, false +} + +// An EntityList contains one or more Entities. +type EntityList []*Entity + +// KeysById returns the set of keys that have the given key id. +func (el EntityList) KeysById(id uint64) (keys []Key) { + for _, e := range el { + if e.PrimaryKey.KeyId == id { + var selfSig *packet.Signature + for _, ident := range e.Identities { + if selfSig == nil { + selfSig = ident.SelfSignature + } else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { + selfSig = ident.SelfSignature + break + } + } + keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig}) + } + + for _, subKey := range e.Subkeys { + if subKey.PublicKey.KeyId == id { + keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig}) + } + } + } + return +} + +// KeysByIdAndUsage returns the set of keys with the given id that also meet +// the key usage given by requiredUsage. The requiredUsage is expressed as +// the bitwise-OR of packet.KeyFlag* values. +func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) { + for _, key := range el.KeysById(id) { + if len(key.Entity.Revocations) > 0 { + continue + } + + if key.SelfSignature.RevocationReason != nil { + continue + } + + if key.SelfSignature.FlagsValid && requiredUsage != 0 { + var usage byte + if key.SelfSignature.FlagCertify { + usage |= packet.KeyFlagCertify + } + if key.SelfSignature.FlagSign { + usage |= packet.KeyFlagSign + } + if key.SelfSignature.FlagEncryptCommunications { + usage |= packet.KeyFlagEncryptCommunications + } + if key.SelfSignature.FlagEncryptStorage { + usage |= packet.KeyFlagEncryptStorage + } + if usage&requiredUsage != requiredUsage { + continue + } + } + + keys = append(keys, key) + } + return +} + +// DecryptionKeys returns all private keys that are valid for decryption. +func (el EntityList) DecryptionKeys() (keys []Key) { + for _, e := range el { + for _, subKey := range e.Subkeys { + if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) { + keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig}) + } + } + } + return +} + +// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file. +func ReadArmoredKeyRing(r io.Reader) (EntityList, error) { + block, err := armor.Decode(r) + if err == io.EOF { + return nil, errors.InvalidArgumentError("no armored data found") + } + if err != nil { + return nil, err + } + if block.Type != PublicKeyType && block.Type != PrivateKeyType { + return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type) + } + + return ReadKeyRing(block.Body) +} + +// ReadKeyRing reads one or more public/private keys. Unsupported keys are +// ignored as long as at least a single valid key is found. +func ReadKeyRing(r io.Reader) (el EntityList, err error) { + packets := packet.NewReader(r) + var lastUnsupportedError error + + for { + var e *Entity + e, err = ReadEntity(packets) + if err != nil { + // TODO: warn about skipped unsupported/unreadable keys + if _, ok := err.(errors.UnsupportedError); ok { + lastUnsupportedError = err + err = readToNextPublicKey(packets) + } else if _, ok := err.(errors.StructuralError); ok { + // Skip unreadable, badly-formatted keys + lastUnsupportedError = err + err = readToNextPublicKey(packets) + } + if err == io.EOF { + err = nil + break + } + if err != nil { + el = nil + break + } + } else { + el = append(el, e) + } + } + + if len(el) == 0 && err == nil { + err = lastUnsupportedError + } + return +} + +// readToNextPublicKey reads packets until the start of the entity and leaves +// the first packet of the new entity in the Reader. +func readToNextPublicKey(packets *packet.Reader) (err error) { + var p packet.Packet + for { + p, err = packets.Next() + if err == io.EOF { + return + } else if err != nil { + if _, ok := err.(errors.UnsupportedError); ok { + err = nil + continue + } + return + } + + if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey { + packets.Unread(p) + return + } + } + + panic("unreachable") +} + +// ReadEntity reads an entity (public key, identities, subkeys etc) from the +// given Reader. +func ReadEntity(packets *packet.Reader) (*Entity, error) { + e := new(Entity) + e.Identities = make(map[string]*Identity) + + p, err := packets.Next() + if err != nil { + return nil, err + } + + var ok bool + if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok { + if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok { + packets.Unread(p) + return nil, errors.StructuralError("first packet was not a public/private key") + } else { + e.PrimaryKey = &e.PrivateKey.PublicKey + } + } + + if !e.PrimaryKey.PubKeyAlgo.CanSign() { + return nil, errors.StructuralError("primary key cannot be used for signatures") + } + + var current *Identity + var revocations []*packet.Signature +EachPacket: + for { + p, err := packets.Next() + if err == io.EOF { + break + } else if err != nil { + return nil, err + } + + switch pkt := p.(type) { + case *packet.UserId: + current = new(Identity) + current.Name = pkt.Id + current.UserId = pkt + e.Identities[pkt.Id] = current + + for { + p, err = packets.Next() + if err == io.EOF { + return nil, io.ErrUnexpectedEOF + } else if err != nil { + return nil, err + } + + sig, ok := p.(*packet.Signature) + if !ok { + return nil, errors.StructuralError("user ID packet not followed by self-signature") + } + + if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId { + if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil { + return nil, errors.StructuralError("user ID self-signature invalid: " + err.Error()) + } + current.SelfSignature = sig + break + } + current.Signatures = append(current.Signatures, sig) + } + case *packet.Signature: + if pkt.SigType == packet.SigTypeKeyRevocation { + revocations = append(revocations, pkt) + } else if pkt.SigType == packet.SigTypeDirectSignature { + // TODO: RFC4880 5.2.1 permits signatures + // directly on keys (eg. to bind additional + // revocation keys). + } else if current == nil { + return nil, errors.StructuralError("signature packet found before user id packet") + } else { + current.Signatures = append(current.Signatures, pkt) + } + case *packet.PrivateKey: + if pkt.IsSubkey == false { + packets.Unread(p) + break EachPacket + } + err = addSubkey(e, packets, &pkt.PublicKey, pkt) + if err != nil { + return nil, err + } + case *packet.PublicKey: + if pkt.IsSubkey == false { + packets.Unread(p) + break EachPacket + } + err = addSubkey(e, packets, pkt, nil) + if err != nil { + return nil, err + } + default: + // we ignore unknown packets + } + } + + if len(e.Identities) == 0 { + return nil, errors.StructuralError("entity without any identities") + } + + for _, revocation := range revocations { + err = e.PrimaryKey.VerifyRevocationSignature(revocation) + if err == nil { + e.Revocations = append(e.Revocations, revocation) + } else { + // TODO: RFC 4880 5.2.3.15 defines revocation keys. + return nil, errors.StructuralError("revocation signature signed by alternate key") + } + } + + return e, nil +} + +func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error { + var subKey Subkey + subKey.PublicKey = pub + subKey.PrivateKey = priv + p, err := packets.Next() + if err == io.EOF { + return io.ErrUnexpectedEOF + } + if err != nil { + return errors.StructuralError("subkey signature invalid: " + err.Error()) + } + var ok bool + subKey.Sig, ok = p.(*packet.Signature) + if !ok { + return errors.StructuralError("subkey packet not followed by signature") + } + if subKey.Sig.SigType != packet.SigTypeSubkeyBinding && subKey.Sig.SigType != packet.SigTypeSubkeyRevocation { + return errors.StructuralError("subkey signature with wrong type") + } + err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, subKey.Sig) + if err != nil { + return errors.StructuralError("subkey signature invalid: " + err.Error()) + } + e.Subkeys = append(e.Subkeys, subKey) + return nil +} + +const defaultRSAKeyBits = 2048 + +// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a +// single identity composed of the given full name, comment and email, any of +// which may be empty but must not contain any of "()<>\x00". +// If config is nil, sensible defaults will be used. +func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) { + currentTime := config.Now() + + uid := packet.NewUserId(name, comment, email) + if uid == nil { + return nil, errors.InvalidArgumentError("user id field contained invalid characters") + } + signingPriv, err := rsa.GenerateKey(config.Random(), defaultRSAKeyBits) + if err != nil { + return nil, err + } + encryptingPriv, err := rsa.GenerateKey(config.Random(), defaultRSAKeyBits) + if err != nil { + return nil, err + } + + e := &Entity{ + PrimaryKey: packet.NewRSAPublicKey(currentTime, &signingPriv.PublicKey), + PrivateKey: packet.NewRSAPrivateKey(currentTime, signingPriv), + Identities: make(map[string]*Identity), + } + isPrimaryId := true + e.Identities[uid.Id] = &Identity{ + Name: uid.Name, + UserId: uid, + SelfSignature: &packet.Signature{ + CreationTime: currentTime, + SigType: packet.SigTypePositiveCert, + PubKeyAlgo: packet.PubKeyAlgoRSA, + Hash: config.Hash(), + IsPrimaryId: &isPrimaryId, + FlagsValid: true, + FlagSign: true, + FlagCertify: true, + IssuerKeyId: &e.PrimaryKey.KeyId, + }, + } + + e.Subkeys = make([]Subkey, 1) + e.Subkeys[0] = Subkey{ + PublicKey: packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey), + PrivateKey: packet.NewRSAPrivateKey(currentTime, encryptingPriv), + Sig: &packet.Signature{ + CreationTime: currentTime, + SigType: packet.SigTypeSubkeyBinding, + PubKeyAlgo: packet.PubKeyAlgoRSA, + Hash: config.Hash(), + FlagsValid: true, + FlagEncryptStorage: true, + FlagEncryptCommunications: true, + IssuerKeyId: &e.PrimaryKey.KeyId, + }, + } + e.Subkeys[0].PublicKey.IsSubkey = true + e.Subkeys[0].PrivateKey.IsSubkey = true + + return e, nil +} + +// SerializePrivate serializes an Entity, including private key material, to +// the given Writer. For now, it must only be used on an Entity returned from +// NewEntity. +// If config is nil, sensible defaults will be used. +func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) { + err = e.PrivateKey.Serialize(w) + if err != nil { + return + } + for _, ident := range e.Identities { + err = ident.UserId.Serialize(w) + if err != nil { + return + } + err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config) + if err != nil { + return + } + err = ident.SelfSignature.Serialize(w) + if err != nil { + return + } + } + for _, subkey := range e.Subkeys { + err = subkey.PrivateKey.Serialize(w) + if err != nil { + return + } + err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config) + if err != nil { + return + } + err = subkey.Sig.Serialize(w) + if err != nil { + return + } + } + return nil +} + +// Serialize writes the public part of the given Entity to w. (No private +// key material will be output). +func (e *Entity) Serialize(w io.Writer) error { + err := e.PrimaryKey.Serialize(w) + if err != nil { + return err + } + for _, ident := range e.Identities { + err = ident.UserId.Serialize(w) + if err != nil { + return err + } + err = ident.SelfSignature.Serialize(w) + if err != nil { + return err + } + for _, sig := range ident.Signatures { + err = sig.Serialize(w) + if err != nil { + return err + } + } + } + for _, subkey := range e.Subkeys { + err = subkey.PublicKey.Serialize(w) + if err != nil { + return err + } + err = subkey.Sig.Serialize(w) + if err != nil { + return err + } + } + return nil +} + +// SignIdentity adds a signature to e, from signer, attesting that identity is +// associated with e. The provided identity must already be an element of +// e.Identities and the private key of signer must have been decrypted if +// necessary. +// If config is nil, sensible defaults will be used. +func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error { + if signer.PrivateKey == nil { + return errors.InvalidArgumentError("signing Entity must have a private key") + } + if signer.PrivateKey.Encrypted { + return errors.InvalidArgumentError("signing Entity's private key must be decrypted") + } + ident, ok := e.Identities[identity] + if !ok { + return errors.InvalidArgumentError("given identity string not found in Entity") + } + + sig := &packet.Signature{ + SigType: packet.SigTypeGenericCert, + PubKeyAlgo: signer.PrivateKey.PubKeyAlgo, + Hash: config.Hash(), + CreationTime: config.Now(), + IssuerKeyId: &signer.PrivateKey.KeyId, + } + if err := sig.SignUserId(identity, e.PrimaryKey, signer.PrivateKey, config); err != nil { + return err + } + ident.Signatures = append(ident.Signatures, sig) + return nil +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/keys_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/keys_test.go new file mode 100644 index 00000000..4fdfe587 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/keys_test.go @@ -0,0 +1,216 @@ +package openpgp + +import ( + "testing" + "time" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet" +) + +func TestKeyExpiry(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(expiringKeyHex)) + entity := kring[0] + + const timeFormat = "2006-01-02" + time1, _ := time.Parse(timeFormat, "2013-07-01") + // The expiringKeyHex key is structured as: + // + // pub 1024R/5E237D8C created: 2013-07-01 expires: 2013-07-31 usage: SC + // sub 1024R/1ABB25A0 created: 2013-07-01 expires: 2013-07-08 usage: E + // sub 1024R/96A672F5 created: 2013-07-01 expires: 2013-07-31 usage: E + // + // So this should select the first, non-expired encryption key. + key, _ := entity.encryptionKey(time1) + if id := key.PublicKey.KeyIdShortString(); id != "1ABB25A0" { + t.Errorf("Expected key 1ABB25A0 at time %s, but got key %s", time1.Format(timeFormat), id) + } + + // Once the first encryption subkey has expired, the second should be + // selected. + time2, _ := time.Parse(timeFormat, "2013-07-09") + key, _ = entity.encryptionKey(time2) + if id := key.PublicKey.KeyIdShortString(); id != "96A672F5" { + t.Errorf("Expected key 96A672F5 at time %s, but got key %s", time2.Format(timeFormat), id) + } + + // Once all the keys have expired, nothing should be returned. + time3, _ := time.Parse(timeFormat, "2013-08-01") + if key, ok := entity.encryptionKey(time3); ok { + t.Errorf("Expected no key at time %s, but got key %s", time3.Format(timeFormat), key.PublicKey.KeyIdShortString()) + } +} + +// TestExternallyRevokableKey attempts to load and parse a key with a third party revocation permission. +func TestExternallyRevocableKey(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(subkeyUsageHex)) + + // The 0xA42704B92866382A key can be revoked by 0xBE3893CB843D0FE70C + // according to this signature that appears within the key: + // :signature packet: algo 1, keyid A42704B92866382A + // version 4, created 1396409682, md5len 0, sigclass 0x1f + // digest algo 2, begin of digest a9 84 + // hashed subpkt 2 len 4 (sig created 2014-04-02) + // hashed subpkt 12 len 22 (revocation key: c=80 a=1 f=CE094AA433F7040BB2DDF0BE3893CB843D0FE70C) + // hashed subpkt 7 len 1 (not revocable) + // subpkt 16 len 8 (issuer key ID A42704B92866382A) + // data: [1024 bits] + + id := uint64(0xA42704B92866382A) + keys := kring.KeysById(id) + if len(keys) != 1 { + t.Errorf("Expected to find key id %X, but got %d matches", id, len(keys)) + } +} + +func TestKeyRevocation(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(revokedKeyHex)) + + // revokedKeyHex contains these keys: + // pub 1024R/9A34F7C0 2014-03-25 [revoked: 2014-03-25] + // sub 1024R/1BA3CD60 2014-03-25 [revoked: 2014-03-25] + ids := []uint64{0xA401D9F09A34F7C0, 0x5CD3BE0A1BA3CD60} + + for _, id := range ids { + keys := kring.KeysById(id) + if len(keys) != 1 { + t.Errorf("Expected KeysById to find revoked key %X, but got %d matches", id, len(keys)) + } + keys = kring.KeysByIdUsage(id, 0) + if len(keys) != 0 { + t.Errorf("Expected KeysByIdUsage to filter out revoked key %X, but got %d matches", id, len(keys)) + } + } +} + +func TestSubkeyRevocation(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(revokedSubkeyHex)) + + // revokedSubkeyHex contains these keys: + // pub 1024R/4EF7E4BECCDE97F0 2014-03-25 + // sub 1024R/D63636E2B96AE423 2014-03-25 + // sub 1024D/DBCE4EE19529437F 2014-03-25 + // sub 1024R/677815E371C2FD23 2014-03-25 [revoked: 2014-03-25] + validKeys := []uint64{0x4EF7E4BECCDE97F0, 0xD63636E2B96AE423, 0xDBCE4EE19529437F} + revokedKey := uint64(0x677815E371C2FD23) + + for _, id := range validKeys { + keys := kring.KeysById(id) + if len(keys) != 1 { + t.Errorf("Expected KeysById to find key %X, but got %d matches", id, len(keys)) + } + keys = kring.KeysByIdUsage(id, 0) + if len(keys) != 1 { + t.Errorf("Expected KeysByIdUsage to find key %X, but got %d matches", id, len(keys)) + } + } + + keys := kring.KeysById(revokedKey) + if len(keys) != 1 { + t.Errorf("Expected KeysById to find key %X, but got %d matches", revokedKey, len(keys)) + } + + keys = kring.KeysByIdUsage(revokedKey, 0) + if len(keys) != 0 { + t.Errorf("Expected KeysByIdUsage to filter out revoked key %X, but got %d matches", revokedKey, len(keys)) + } +} + +func TestKeyUsage(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(subkeyUsageHex)) + + // subkeyUsageHex contains these keys: + // pub 1024R/2866382A created: 2014-04-01 expires: never usage: SC + // sub 1024R/936C9153 created: 2014-04-01 expires: never usage: E + // sub 1024R/64D5F5BB created: 2014-04-02 expires: never usage: E + // sub 1024D/BC0BA992 created: 2014-04-02 expires: never usage: S + certifiers := []uint64{0xA42704B92866382A} + signers := []uint64{0xA42704B92866382A, 0x42CE2C64BC0BA992} + encrypters := []uint64{0x09C0C7D9936C9153, 0xC104E98664D5F5BB} + + for _, id := range certifiers { + keys := kring.KeysByIdUsage(id, packet.KeyFlagCertify) + if len(keys) == 1 { + if keys[0].PublicKey.KeyId != id { + t.Errorf("Expected to find certifier key id %X, but got %X", id, keys[0].PublicKey.KeyId) + } + } else { + t.Errorf("Expected one match for certifier key id %X, but got %d matches", id, len(keys)) + } + } + + for _, id := range signers { + keys := kring.KeysByIdUsage(id, packet.KeyFlagSign) + if len(keys) == 1 { + if keys[0].PublicKey.KeyId != id { + t.Errorf("Expected to find signing key id %X, but got %X", id, keys[0].PublicKey.KeyId) + } + } else { + t.Errorf("Expected one match for signing key id %X, but got %d matches", id, len(keys)) + } + + // This keyring contains no encryption keys that are also good for signing. + keys = kring.KeysByIdUsage(id, packet.KeyFlagEncryptStorage|packet.KeyFlagEncryptCommunications) + if len(keys) != 0 { + t.Errorf("Unexpected match for encryption key id %X", id) + } + } + + for _, id := range encrypters { + keys := kring.KeysByIdUsage(id, packet.KeyFlagEncryptStorage|packet.KeyFlagEncryptCommunications) + if len(keys) == 1 { + if keys[0].PublicKey.KeyId != id { + t.Errorf("Expected to find encryption key id %X, but got %X", id, keys[0].PublicKey.KeyId) + } + } else { + t.Errorf("Expected one match for encryption key id %X, but got %d matches", id, len(keys)) + } + + // This keyring contains no encryption keys that are also good for signing. + keys = kring.KeysByIdUsage(id, packet.KeyFlagSign) + if len(keys) != 0 { + t.Errorf("Unexpected match for signing key id %X", id) + } + } +} + +func TestIdVerification(t *testing.T) { + kring, err := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) + if err != nil { + t.Fatal(err) + } + if err := kring[1].PrivateKey.Decrypt([]byte("passphrase")); err != nil { + t.Fatal(err) + } + + const identity = "Test Key 1 (RSA)" + if err := kring[0].SignIdentity(identity, kring[1], nil); err != nil { + t.Fatal(err) + } + + ident, ok := kring[0].Identities[identity] + if !ok { + t.Fatal("identity missing from key after signing") + } + + checked := false + for _, sig := range ident.Signatures { + if sig.IssuerKeyId == nil || *sig.IssuerKeyId != kring[1].PrimaryKey.KeyId { + continue + } + + if err := kring[1].PrimaryKey.VerifyUserIdSignature(identity, kring[0].PrimaryKey, sig); err != nil { + t.Fatalf("error verifying new identity signature: %s", err) + } + checked = true + break + } + + if !checked { + t.Fatal("didn't find identity signature in Entity") + } +} + +const expiringKeyHex = "988d0451d1ec5d010400ba3385721f2dc3f4ab096b2ee867ab77213f0a27a8538441c35d2fa225b08798a1439a66a5150e6bdc3f40f5d28d588c712394c632b6299f77db8c0d48d37903fb72ebd794d61be6aa774688839e5fdecfe06b2684cc115d240c98c66cb1ef22ae84e3aa0c2b0c28665c1e7d4d044e7f270706193f5223c8d44e0d70b7b8da830011010001b40f4578706972792074657374206b657988be041301020028050251d1ec5d021b03050900278d00060b090807030206150802090a0b0416020301021e01021780000a091072589ad75e237d8c033503fd10506d72837834eb7f994117740723adc39227104b0d326a1161871c0b415d25b4aedef946ca77ea4c05af9c22b32cf98be86ab890111fced1ee3f75e87b7cc3c00dc63bbc85dfab91c0dc2ad9de2c4d13a34659333a85c6acc1a669c5e1d6cecb0cf1e56c10e72d855ae177ddc9e766f9b2dda57ccbb75f57156438bbdb4e42b88d0451d1ec5d0104009c64906559866c5cb61578f5846a94fcee142a489c9b41e67b12bb54cfe86eb9bc8566460f9a720cb00d6526fbccfd4f552071a8e3f7744b1882d01036d811ee5a3fb91a1c568055758f43ba5d2c6a9676b012f3a1a89e47bbf624f1ad571b208f3cc6224eb378f1645dd3d47584463f9eadeacfd1ce6f813064fbfdcc4b5a53001101000188a504180102000f021b0c050251d1f06b050900093e89000a091072589ad75e237d8c20e00400ab8310a41461425b37889c4da28129b5fae6084fafbc0a47dd1adc74a264c6e9c9cc125f40462ee1433072a58384daef88c961c390ed06426a81b464a53194c4e291ddd7e2e2ba3efced01537d713bd111f48437bde2363446200995e8e0d4e528dda377fd1e8f8ede9c8e2198b393bd86852ce7457a7e3daf74d510461a5b77b88d0451d1ece8010400b3a519f83ab0010307e83bca895170acce8964a044190a2b368892f7a244758d9fc193482648acb1fb9780d28cc22d171931f38bb40279389fc9bf2110876d4f3db4fcfb13f22f7083877fe56592b3b65251312c36f83ffcb6d313c6a17f197dd471f0712aad15a8537b435a92471ba2e5b0c72a6c72536c3b567c558d7b6051001101000188a504180102000f021b0c050251d1f07b050900279091000a091072589ad75e237d8ce69e03fe286026afacf7c97ee20673864d4459a2240b5655219950643c7dba0ac384b1d4359c67805b21d98211f7b09c2a0ccf6410c8c04d4ff4a51293725d8d6570d9d8bb0e10c07d22357caeb49626df99c180be02d77d1fe8ed25e7a54481237646083a9f89a11566cd20b9e995b1487c5f9e02aeb434f3a1897cd416dd0a87861838da3e9e" +const subkeyUsageHex = "988d04533a52bc010400d26af43085558f65b9e7dbc90cb9238015259aed5e954637adcfa2181548b2d0b60c65f1f42ec5081cbf1bc0a8aa4900acfb77070837c58f26012fbce297d70afe96e759ad63531f0037538e70dbf8e384569b9720d99d8eb39d8d0a2947233ed242436cb6ac7dfe74123354b3d0119b5c235d3dd9c9d6c004f8ffaf67ad8583001101000188b7041f010200210502533b8552170c8001ce094aa433f7040bb2ddf0be3893cb843d0fe70c020700000a0910a42704b92866382aa98404009d63d916a27543da4221c60087c33f1c44bec9998c5438018ed370cca4962876c748e94b73eb39c58eb698063f3fd6346d58dd2a11c0247934c4a9d71f24754f7468f96fb24c3e791dd2392b62f626148ad724189498cbf993db2df7c0cdc2d677c35da0f16cb16c9ce7c33b4de65a4a91b1d21a130ae9cc26067718910ef8e2b417556d627261203c756d627261407379642e65642e61753e88b80413010200220502533a52bc021b03060b090807030206150802090a0b0416020301021e01021780000a0910a42704b92866382a47840400c0c2bd04f5fca586de408b395b3c280a278259c93eaaa8b79a53b97003f8ed502a8a00446dd9947fb462677e4fcac0dac2f0701847d15130aadb6cd9e0705ea0cf5f92f129136c7be21a718d46c8e641eb7f044f2adae573e11ae423a0a9ca51324f03a8a2f34b91fa40c3cc764bee4dccadedb54c768ba0469b683ea53f1c29b88d04533a52bc01040099c92a5d6f8b744224da27bc2369127c35269b58bec179de6bbc038f749344222f85a31933224f26b70243c4e4b2d242f0c4777eaef7b5502f9dad6d8bf3aaeb471210674b74de2d7078af497d55f5cdad97c7bedfbc1b41e8065a97c9c3d344b21fc81d27723af8e374bc595da26ea242dccb6ae497be26eea57e563ed517e90011010001889f0418010200090502533a52bc021b0c000a0910a42704b92866382afa1403ff70284c2de8a043ff51d8d29772602fa98009b7861c540535f874f2c230af8caf5638151a636b21f8255003997ccd29747fdd06777bb24f9593bd7d98a3e887689bf902f999915fcc94625ae487e5d13e6616f89090ebc4fdc7eb5cad8943e4056995bb61c6af37f8043016876a958ec7ebf39c43d20d53b7f546cfa83e8d2604b88d04533b8283010400c0b529316dbdf58b4c54461e7e669dc11c09eb7f73819f178ccd4177b9182b91d138605fcf1e463262fabefa73f94a52b5e15d1904635541c7ea540f07050ce0fb51b73e6f88644cec86e91107c957a114f69554548a85295d2b70bd0b203992f76eb5d493d86d9eabcaa7ef3fc7db7e458438db3fcdb0ca1cc97c638439a9170011010001889f0418010200090502533b8283021b0c000a0910a42704b92866382adc6d0400cfff6258485a21675adb7a811c3e19ebca18851533f75a7ba317950b9997fda8d1a4c8c76505c08c04b6c2cc31dc704d33da36a21273f2b388a1a706f7c3378b66d887197a525936ed9a69acb57fe7f718133da85ec742001c5d1864e9c6c8ea1b94f1c3759cebfd93b18606066c063a63be86085b7e37bdbc65f9a915bf084bb901a204533b85cd110400aed3d2c52af2b38b5b67904b0ef73d6dd7aef86adb770e2b153cd22489654dcc91730892087bb9856ae2d9f7ed1eb48f214243fe86bfe87b349ebd7c30e630e49c07b21fdabf78b7a95c8b7f969e97e3d33f2e074c63552ba64a2ded7badc05ce0ea2be6d53485f6900c7860c7aa76560376ce963d7271b9b54638a4028b573f00a0d8854bfcdb04986141568046202192263b9b67350400aaa1049dbc7943141ef590a70dcb028d730371d92ea4863de715f7f0f16d168bd3dc266c2450457d46dcbbf0b071547e5fbee7700a820c3750b236335d8d5848adb3c0da010e998908dfd93d961480084f3aea20b247034f8988eccb5546efaa35a92d0451df3aaf1aee5aa36a4c4d462c760ecd9cebcabfbe1412b1f21450f203fd126687cd486496e971a87fd9e1a8a765fe654baa219a6871ab97768596ab05c26c1aeea8f1a2c72395a58dbc12ef9640d2b95784e974a4d2d5a9b17c25fedacfe551bda52602de8f6d2e48443f5dd1a2a2a8e6a5e70ecdb88cd6e766ad9745c7ee91d78cc55c3d06536b49c3fee6c3d0b6ff0fb2bf13a314f57c953b8f4d93bf88e70418010200090502533b85cd021b0200520910a42704b92866382a47200419110200060502533b85cd000a091042ce2c64bc0ba99214b2009e26b26852c8b13b10c35768e40e78fbbb48bd084100a0c79d9ea0844fa5853dd3c85ff3ecae6f2c9dd6c557aa04008bbbc964cd65b9b8299d4ebf31f41cc7264b8cf33a00e82c5af022331fac79efc9563a822497ba012953cefe2629f1242fcdcb911dbb2315985bab060bfd58261ace3c654bdbbe2e8ed27a46e836490145c86dc7bae15c011f7e1ffc33730109b9338cd9f483e7cef3d2f396aab5bd80efb6646d7e778270ee99d934d187dd98" +const revokedKeyHex = "988d045331ce82010400c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be10011010001889f04200102000905025331d0e3021d03000a0910a401d9f09a34f7c042aa040086631196405b7e6af71026b88e98012eab44aa9849f6ef3fa930c7c9f23deaedba9db1538830f8652fb7648ec3fcade8dbcbf9eaf428e83c6cbcc272201bfe2fbb90d41963397a7c0637a1a9d9448ce695d9790db2dc95433ad7be19eb3de72dacf1d6db82c3644c13eae2a3d072b99bb341debba012c5ce4006a7d34a1f4b94b444526567205265766f6b657220283c52656727732022424d204261726973746122204b657920262530305c303e5c29203c72656740626d626172697374612e636f2e61753e88b704130102002205025331ce82021b03060b090807030206150802090a0b0416020301021e01021780000a0910a401d9f09a34f7c0019c03f75edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56889c04100102000605025331cfb5000a0910fe9645554e8266b64b4303fc084075396674fb6f778d302ac07cef6bc0b5d07b66b2004c44aef711cbac79617ef06d836b4957522d8772dd94bf41a2f4ac8b1ee6d70c57503f837445a74765a076d07b829b8111fc2a918423ddb817ead7ca2a613ef0bfb9c6b3562aec6c3cf3c75ef3031d81d95f6563e4cdcc9960bcb386c5d757b104fcca5fe11fc709df884604101102000605025331cfe7000a09107b15a67f0b3ddc0317f6009e360beea58f29c1d963a22b962b80788c3fa6c84e009d148cfde6b351469b8eae91187eff07ad9d08fcaab88d045331ce820104009f25e20a42b904f3fa555530fe5c46737cf7bd076c35a2a0d22b11f7e0b61a69320b768f4a80fe13980ce380d1cfc4a0cd8fbe2d2e2ef85416668b77208baa65bf973fe8e500e78cc310d7c8705cdb34328bf80e24f0385fce5845c33bc7943cf6b11b02348a23da0bf6428e57c05135f2dc6bd7c1ce325d666d5a5fd2fd5e410011010001889f04180102000905025331ce82021b0c000a0910a401d9f09a34f7c0418003fe34feafcbeaef348a800a0d908a7a6809cc7304017d820f70f0474d5e23cb17e38b67dc6dca282c6ca00961f4ec9edf2738d0f087b1d81e4871ef08e1798010863afb4eac4c44a376cb343be929c5be66a78cfd4456ae9ec6a99d97f4e1c3ff3583351db2147a65c0acef5c003fb544ab3a2e2dc4d43646f58b811a6c3a369d1f" +const revokedSubkeyHex = "988d04533121f6010400aefc803a3e4bb1a61c86e8a86d2726c6a43e0079e9f2713f1fa017e9854c83877f4aced8e331d675c67ea83ddab80aacbfa0b9040bb12d96f5a3d6be09455e2a76546cbd21677537db941cab710216b6d24ec277ee0bd65b910f416737ed120f6b93a9d3b306245c8cfd8394606fdb462e5cf43c551438d2864506c63367fc890011010001b41d416c696365203c616c69636540626d626172697374612e636f2e61753e88bb041301020025021b03060b090807030206150802090a0b0416020301021e01021780050253312798021901000a09104ef7e4beccde97f015a803ff5448437780f63263b0df8442a995e7f76c221351a51edd06f2063d8166cf3157aada4923dfc44aa0f2a6a4da5cf83b7fe722ba8ab416c976e77c6b5682e7f1069026673bd0de56ba06fd5d7a9f177607f277d9b55ff940a638c3e68525c67517e2b3d976899b93ca267f705b3e5efad7d61220e96b618a4497eab8d04403d23f8846041011020006050253312910000a09107b15a67f0b3ddc03d96e009f50b6365d86c4be5d5e9d0ea42d5e56f5794c617700a0ab274e19c2827780016d23417ce89e0a2c0d987d889c04100102000605025331cf7a000a0910a401d9f09a34f7c0ee970400aca292f213041c9f3b3fc49148cbda9d84afee6183c8dd6c5ff2600b29482db5fecd4303797be1ee6d544a20a858080fec43412061c9a71fae4039fd58013b4ae341273e6c66ad4c7cdd9e68245bedb260562e7b166f2461a1032f2b38c0e0e5715fb3d1656979e052b55ca827a76f872b78a9fdae64bc298170bfcebedc1271b41a416c696365203c616c696365407379646973702e6f722e61753e88b804130102002205025331278b021b03060b090807030206150802090a0b0416020301021e01021780000a09104ef7e4beccde97f06a7003fa03c3af68d272ebc1fa08aa72a03b02189c26496a2833d90450801c4e42c5b5f51ad96ce2d2c9cef4b7c02a6a2fcf1412d6a2d486098eb762f5010a201819c17fd2888aec8eda20c65a3b75744de7ee5cc8ac7bfc470cbe3cb982720405a27a3c6a8c229cfe36905f881b02ed5680f6a8f05866efb9d6c5844897e631deb949ca8846041011020006050253312910000a09107b15a67f0b3ddc0347bc009f7fa35db59147469eb6f2c5aaf6428accb138b22800a0caa2f5f0874bacc5909c652a57a31beda65eddd5889c04100102000605025331cf7a000a0910a401d9f09a34f7c0316403ff46f2a5c101256627f16384d34a38fb47a6c88ba60506843e532d91614339fccae5f884a5741e7582ffaf292ba38ee10a270a05f139bde3814b6a077e8cd2db0f105ebea2a83af70d385f13b507fac2ad93ff79d84950328bb86f3074745a8b7f9b64990fb142e2a12976e27e8d09a28dc5621f957ac49091116da410ac3cbde1b88d04533121f6010400cbd785b56905e4192e2fb62a720727d43c4fa487821203cf72138b884b78b701093243e1d8c92a0248a6c0203a5a88693da34af357499abacaf4b3309c640797d03093870a323b4b6f37865f6eaa2838148a67df4735d43a90ca87942554cdf1c4a751b1e75f9fd4ce4e97e278d6c1c7ed59d33441df7d084f3f02beb68896c70011010001889f0418010200090502533121f6021b0c000a09104ef7e4beccde97f0b98b03fc0a5ccf6a372995835a2f5da33b282a7d612c0ab2a97f59cf9fff73e9110981aac2858c41399afa29624a7fd8a0add11654e3d882c0fd199e161bdad65e5e2548f7b68a437ea64293db1246e3011cbb94dc1bcdeaf0f2539bd88ff16d95547144d97cead6a8c5927660a91e6db0d16eb36b7b49a3525b54d1644e65599b032b7eb901a204533127a0110400bd3edaa09eff9809c4edc2c2a0ebe52e53c50a19c1e49ab78e6167bf61473bb08f2050d78a5cbbc6ed66aff7b42cd503f16b4a0b99fa1609681fca9b7ce2bbb1a5b3864d6cdda4d7ef7849d156d534dea30fb0efb9e4cf8959a2b2ce623905882d5430b995a15c3b9fe92906086788b891002924f94abe139b42cbbfaaabe42f00a0b65dc1a1ad27d798adbcb5b5ad02d2688c89477b03ff4eebb6f7b15a73b96a96bed201c0e5e4ea27e4c6e2dd1005b94d4b90137a5b1cf5e01c6226c070c4cc999938101578877ee76d296b9aab8246d57049caacf489e80a3f40589cade790a020b1ac146d6f7a6241184b8c7fcde680eae3188f5dcbe846d7f7bdad34f6fcfca08413e19c1d5df83fc7c7c627d493492e009c2f52a80400a2fe82de87136fd2e8845888c4431b032ba29d9a29a804277e31002a8201fb8591a3e55c7a0d0881496caf8b9fb07544a5a4879291d0dc026a0ea9e5bd88eb4aa4947bbd694b25012e208a250d65ddc6f1eea59d3aed3b4ec15fcab85e2afaa23a40ab1ef9ce3e11e1bc1c34a0e758e7aa64deb8739276df0af7d4121f834a9b88e70418010200090502533127a0021b02005209104ef7e4beccde97f047200419110200060502533127a0000a0910dbce4ee19529437fe045009c0b32f5ead48ee8a7e98fac0dea3d3e6c0e2c552500a0ad71fadc5007cfaf842d9b7db3335a8cdad15d3d1a6404009b08e2c68fe8f3b45c1bb72a4b3278cdf3012aa0f229883ad74aa1f6000bb90b18301b2f85372ca5d6b9bf478d235b733b1b197d19ccca48e9daf8e890cb64546b4ce1b178faccfff07003c172a2d4f5ebaba9f57153955f3f61a9b80a4f5cb959908f8b211b03b7026a8a82fc612bfedd3794969bcf458c4ce92be215a1176ab88d045331d144010400a5063000c5aaf34953c1aa3bfc95045b3aab9882b9a8027fecfe2142dc6b47ba8aca667399990244d513dd0504716908c17d92c65e74219e004f7b83fc125e575dd58efec3ab6dd22e3580106998523dea42ec75bf9aa111734c82df54630bebdff20fe981cfc36c76f865eb1c2fb62c9e85bc3a6e5015a361a2eb1c8431578d0011010001889f04280102000905025331d433021d03000a09104ef7e4beccde97f02e5503ff5e0630d1b65291f4882b6d40a29da4616bb5088717d469fbcc3648b8276de04a04988b1f1b9f3e18f52265c1f8b6c85861691c1a6b8a3a25a1809a0b32ad330aec5667cb4262f4450649184e8113849b05e5ad06a316ea80c001e8e71838190339a6e48bbde30647bcf245134b9a97fa875c1d83a9862cae87ffd7e2c4ce3a1b89013d04180102000905025331d144021b0200a809104ef7e4beccde97f09d2004190102000605025331d144000a0910677815e371c2fd23522203fe22ab62b8e7a151383cea3edd3a12995693911426f8ccf125e1f6426388c0010f88d9ca7da2224aee8d1c12135998640c5e1813d55a93df472faae75bef858457248db41b4505827590aeccf6f9eb646da7f980655dd3050c6897feddddaca90676dee856d66db8923477d251712bb9b3186b4d0114daf7d6b59272b53218dd1da94a03ff64006fcbe71211e5daecd9961fba66cdb6de3f914882c58ba5beddeba7dcb950c1156d7fba18c19ea880dccc800eae335deec34e3b84ac75ffa24864f782f87815cda1c0f634b3dd2fa67cea30811d21723d21d9551fa12ccbcfa62b6d3a15d01307b99925707992556d50065505b090aadb8579083a20fe65bd2a270da9b011" diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/compressed.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/compressed.go new file mode 100644 index 00000000..eb7ce0fd --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/compressed.go @@ -0,0 +1,123 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "compress/bzip2" + "compress/flate" + "compress/zlib" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "io" + "strconv" +) + +// Compressed represents a compressed OpenPGP packet. The decompressed contents +// will contain more OpenPGP packets. See RFC 4880, section 5.6. +type Compressed struct { + Body io.Reader +} + +const ( + NoCompression = flate.NoCompression + BestSpeed = flate.BestSpeed + BestCompression = flate.BestCompression + DefaultCompression = flate.DefaultCompression +) + +// CompressionConfig contains compressor configuration settings. +type CompressionConfig struct { + // Level is the compression level to use. It must be set to + // between -1 and 9, with -1 causing the compressor to use the + // default compression level, 0 causing the compressor to use + // no compression and 1 to 9 representing increasing (better, + // slower) compression levels. If Level is less than -1 or + // more then 9, a non-nil error will be returned during + // encryption. See the constants above for convenient common + // settings for Level. + Level int +} + +func (c *Compressed) parse(r io.Reader) error { + var buf [1]byte + _, err := readFull(r, buf[:]) + if err != nil { + return err + } + + switch buf[0] { + case 1: + c.Body = flate.NewReader(r) + case 2: + c.Body, err = zlib.NewReader(r) + case 3: + c.Body = bzip2.NewReader(r) + default: + err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0]))) + } + + return err +} + +// compressedWriterCloser represents the serialized compression stream +// header and the compressor. Its Close() method ensures that both the +// compressor and serialized stream header are closed. Its Write() +// method writes to the compressor. +type compressedWriteCloser struct { + sh io.Closer // Stream Header + c io.WriteCloser // Compressor +} + +func (cwc compressedWriteCloser) Write(p []byte) (int, error) { + return cwc.c.Write(p) +} + +func (cwc compressedWriteCloser) Close() (err error) { + err = cwc.c.Close() + if err != nil { + return err + } + + return cwc.sh.Close() +} + +// SerializeCompressed serializes a compressed data packet to w and +// returns a WriteCloser to which the literal data packets themselves +// can be written and which MUST be closed on completion. If cc is +// nil, sensible defaults will be used to configure the compression +// algorithm. +func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) { + compressed, err := serializeStreamHeader(w, packetTypeCompressed) + if err != nil { + return + } + + _, err = compressed.Write([]byte{uint8(algo)}) + if err != nil { + return + } + + level := DefaultCompression + if cc != nil { + level = cc.Level + } + + var compressor io.WriteCloser + switch algo { + case CompressionZIP: + compressor, err = flate.NewWriter(compressed, level) + case CompressionZLIB: + compressor, err = zlib.NewWriterLevel(compressed, level) + default: + s := strconv.Itoa(int(algo)) + err = errors.UnsupportedError("Unsupported compression algorithm: " + s) + } + if err != nil { + return + } + + literaldata = compressedWriteCloser{compressed, compressor} + + return +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/compressed_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/compressed_test.go new file mode 100644 index 00000000..cb2d70bd --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/compressed_test.go @@ -0,0 +1,41 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "encoding/hex" + "io" + "io/ioutil" + "testing" +) + +func TestCompressed(t *testing.T) { + packet, err := Read(readerFromHex(compressedHex)) + if err != nil { + t.Errorf("failed to read Compressed: %s", err) + return + } + + c, ok := packet.(*Compressed) + if !ok { + t.Error("didn't find Compressed packet") + return + } + + contents, err := ioutil.ReadAll(c.Body) + if err != nil && err != io.EOF { + t.Error(err) + return + } + + expected, _ := hex.DecodeString(compressedExpectedHex) + if !bytes.Equal(expected, contents) { + t.Errorf("got:%x want:%x", contents, expected) + } +} + +const compressedHex = "a3013b2d90c4e02b72e25f727e5e496a5e49b11e1700" +const compressedExpectedHex = "cb1062004d14c8fe636f6e74656e74732e0a" diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/config.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/config.go new file mode 100644 index 00000000..d977cde6 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/config.go @@ -0,0 +1,88 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "crypto" + "crypto/rand" + "io" + "time" +) + +// Config collects a number of parameters along with sensible defaults. +// A nil *Config is valid and results in all default values. +type Config struct { + // Rand provides the source of entropy. + // If nil, the crypto/rand Reader is used. + Rand io.Reader + // DefaultHash is the default hash function to be used. + // If zero, SHA-256 is used. + DefaultHash crypto.Hash + // DefaultCipher is the cipher to be used. + // If zero, AES-128 is used. + DefaultCipher CipherFunction + // Time returns the current time as the number of seconds since the + // epoch. If Time is nil, time.Now is used. + Time func() time.Time + // DefaultCompressionAlgo is the compression algorithm to be + // applied to the plaintext before encryption. If zero, no + // compression is done. + DefaultCompressionAlgo CompressionAlgo + // CompressionConfig configures the compression settings. + CompressionConfig *CompressionConfig + // S2KCount is only used for symmetric encryption. It + // determines the strength of the passphrase stretching when + // the said passphrase is hashed to produce a key. S2KCount + // should be between 1024 and 65011712, inclusive. If Config + // is nil or S2KCount is 0, the value 65536 used. Not all + // values in the above range can be represented. S2KCount will + // be rounded up to the next representable value if it cannot + // be encoded exactly. When set, it is strongly encrouraged to + // use a value that is at least 65536. See RFC 4880 Section + // 3.7.1.3. + S2KCount int +} + +func (c *Config) Random() io.Reader { + if c == nil || c.Rand == nil { + return rand.Reader + } + return c.Rand +} + +func (c *Config) Hash() crypto.Hash { + if c == nil || uint(c.DefaultHash) == 0 { + return crypto.SHA256 + } + return c.DefaultHash +} + +func (c *Config) Cipher() CipherFunction { + if c == nil || uint8(c.DefaultCipher) == 0 { + return CipherAES128 + } + return c.DefaultCipher +} + +func (c *Config) Now() time.Time { + if c == nil || c.Time == nil { + return time.Now() + } + return c.Time() +} + +func (c *Config) Compression() CompressionAlgo { + if c == nil { + return CompressionNone + } + return c.DefaultCompressionAlgo +} + +func (c *Config) PasswordHashIterations() int { + if c == nil || c.S2KCount == 0 { + return 0 + } + return c.S2KCount +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/encrypted_key.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/encrypted_key.go new file mode 100644 index 00000000..fa0353cf --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/encrypted_key.go @@ -0,0 +1,168 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "crypto/rsa" + "encoding/binary" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/elgamal" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "io" + "math/big" + "strconv" +) + +const encryptedKeyVersion = 3 + +// EncryptedKey represents a public-key encrypted session key. See RFC 4880, +// section 5.1. +type EncryptedKey struct { + KeyId uint64 + Algo PublicKeyAlgorithm + CipherFunc CipherFunction // only valid after a successful Decrypt + Key []byte // only valid after a successful Decrypt + + encryptedMPI1, encryptedMPI2 []byte +} + +func (e *EncryptedKey) parse(r io.Reader) (err error) { + var buf [10]byte + _, err = readFull(r, buf[:]) + if err != nil { + return + } + if buf[0] != encryptedKeyVersion { + return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0]))) + } + e.KeyId = binary.BigEndian.Uint64(buf[1:9]) + e.Algo = PublicKeyAlgorithm(buf[9]) + switch e.Algo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: + e.encryptedMPI1, _, err = readMPI(r) + case PubKeyAlgoElGamal: + e.encryptedMPI1, _, err = readMPI(r) + if err != nil { + return + } + e.encryptedMPI2, _, err = readMPI(r) + } + _, err = consumeAll(r) + return +} + +func checksumKeyMaterial(key []byte) uint16 { + var checksum uint16 + for _, v := range key { + checksum += uint16(v) + } + return checksum +} + +// Decrypt decrypts an encrypted session key with the given private key. The +// private key must have been decrypted first. +// If config is nil, sensible defaults will be used. +func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error { + var err error + var b []byte + + // TODO(agl): use session key decryption routines here to avoid + // padding oracle attacks. + switch priv.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: + b, err = rsa.DecryptPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1) + case PubKeyAlgoElGamal: + c1 := new(big.Int).SetBytes(e.encryptedMPI1) + c2 := new(big.Int).SetBytes(e.encryptedMPI2) + b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2) + default: + err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo))) + } + + if err != nil { + return err + } + + e.CipherFunc = CipherFunction(b[0]) + e.Key = b[1 : len(b)-2] + expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1]) + checksum := checksumKeyMaterial(e.Key) + if checksum != expectedChecksum { + return errors.StructuralError("EncryptedKey checksum incorrect") + } + + return nil +} + +// SerializeEncryptedKey serializes an encrypted key packet to w that contains +// key, encrypted to pub. +// If config is nil, sensible defaults will be used. +func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error { + var buf [10]byte + buf[0] = encryptedKeyVersion + binary.BigEndian.PutUint64(buf[1:9], pub.KeyId) + buf[9] = byte(pub.PubKeyAlgo) + + keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */) + keyBlock[0] = byte(cipherFunc) + copy(keyBlock[1:], key) + checksum := checksumKeyMaterial(key) + keyBlock[1+len(key)] = byte(checksum >> 8) + keyBlock[1+len(key)+1] = byte(checksum) + + switch pub.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: + return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock) + case PubKeyAlgoElGamal: + return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock) + case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly: + return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) + } + + return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) +} + +func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error { + cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock) + if err != nil { + return errors.InvalidArgumentError("RSA encryption failed: " + err.Error()) + } + + packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText) + + err = serializeHeader(w, packetTypeEncryptedKey, packetLen) + if err != nil { + return err + } + _, err = w.Write(header[:]) + if err != nil { + return err + } + return writeMPI(w, 8*uint16(len(cipherText)), cipherText) +} + +func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error { + c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock) + if err != nil { + return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error()) + } + + packetLen := 10 /* header length */ + packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8 + packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8 + + err = serializeHeader(w, packetTypeEncryptedKey, packetLen) + if err != nil { + return err + } + _, err = w.Write(header[:]) + if err != nil { + return err + } + err = writeBig(w, c1) + if err != nil { + return err + } + return writeBig(w, c2) +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go new file mode 100644 index 00000000..0a8dcc6d --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go @@ -0,0 +1,125 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "crypto/rsa" + "fmt" + "math/big" + "testing" +) + +func bigFromBase10(s string) *big.Int { + b, ok := new(big.Int).SetString(s, 10) + if !ok { + panic("bigFromBase10 failed") + } + return b +} + +var encryptedKeyPub = rsa.PublicKey{ + E: 65537, + N: bigFromBase10("115804063926007623305902631768113868327816898845124614648849934718568541074358183759250136204762053879858102352159854352727097033322663029387610959884180306668628526686121021235757016368038585212410610742029286439607686208110250133174279811431933746643015923132833417396844716207301518956640020862630546868823"), +} + +var encryptedKeyRSAPriv = &rsa.PrivateKey{ + PublicKey: encryptedKeyPub, + D: bigFromBase10("32355588668219869544751561565313228297765464314098552250409557267371233892496951383426602439009993875125222579159850054973310859166139474359774543943714622292329487391199285040721944491839695981199720170366763547754915493640685849961780092241140181198779299712578774460837139360803883139311171713302987058393"), +} + +var encryptedKeyPriv = &PrivateKey{ + PublicKey: PublicKey{ + PubKeyAlgo: PubKeyAlgoRSA, + }, + PrivateKey: encryptedKeyRSAPriv, +} + +func TestDecryptingEncryptedKey(t *testing.T) { + const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8" + const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b" + + p, err := Read(readerFromHex(encryptedKeyHex)) + if err != nil { + t.Errorf("error from Read: %s", err) + return + } + ek, ok := p.(*EncryptedKey) + if !ok { + t.Errorf("didn't parse an EncryptedKey, got %#v", p) + return + } + + if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA { + t.Errorf("unexpected EncryptedKey contents: %#v", ek) + return + } + + err = ek.Decrypt(encryptedKeyPriv, nil) + if err != nil { + t.Errorf("error from Decrypt: %s", err) + return + } + + if ek.CipherFunc != CipherAES256 { + t.Errorf("unexpected EncryptedKey contents: %#v", ek) + return + } + + keyHex := fmt.Sprintf("%x", ek.Key) + if keyHex != expectedKeyHex { + t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex) + } +} + +func TestEncryptingEncryptedKey(t *testing.T) { + key := []byte{1, 2, 3, 4} + const expectedKeyHex = "01020304" + const keyId = 42 + + pub := &PublicKey{ + PublicKey: &encryptedKeyPub, + KeyId: keyId, + PubKeyAlgo: PubKeyAlgoRSAEncryptOnly, + } + + buf := new(bytes.Buffer) + err := SerializeEncryptedKey(buf, pub, CipherAES128, key, nil) + if err != nil { + t.Errorf("error writing encrypted key packet: %s", err) + } + + p, err := Read(buf) + if err != nil { + t.Errorf("error from Read: %s", err) + return + } + ek, ok := p.(*EncryptedKey) + if !ok { + t.Errorf("didn't parse an EncryptedKey, got %#v", p) + return + } + + if ek.KeyId != keyId || ek.Algo != PubKeyAlgoRSAEncryptOnly { + t.Errorf("unexpected EncryptedKey contents: %#v", ek) + return + } + + err = ek.Decrypt(encryptedKeyPriv, nil) + if err != nil { + t.Errorf("error from Decrypt: %s", err) + return + } + + if ek.CipherFunc != CipherAES128 { + t.Errorf("unexpected EncryptedKey contents: %#v", ek) + return + } + + keyHex := fmt.Sprintf("%x", ek.Key) + if keyHex != expectedKeyHex { + t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex) + } +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/literal.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/literal.go new file mode 100644 index 00000000..1a9ec6e5 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/literal.go @@ -0,0 +1,89 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "encoding/binary" + "io" +) + +// LiteralData represents an encrypted file. See RFC 4880, section 5.9. +type LiteralData struct { + IsBinary bool + FileName string + Time uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined. + Body io.Reader +} + +// ForEyesOnly returns whether the contents of the LiteralData have been marked +// as especially sensitive. +func (l *LiteralData) ForEyesOnly() bool { + return l.FileName == "_CONSOLE" +} + +func (l *LiteralData) parse(r io.Reader) (err error) { + var buf [256]byte + + _, err = readFull(r, buf[:2]) + if err != nil { + return + } + + l.IsBinary = buf[0] == 'b' + fileNameLen := int(buf[1]) + + _, err = readFull(r, buf[:fileNameLen]) + if err != nil { + return + } + + l.FileName = string(buf[:fileNameLen]) + + _, err = readFull(r, buf[:4]) + if err != nil { + return + } + + l.Time = binary.BigEndian.Uint32(buf[:4]) + l.Body = r + return +} + +// SerializeLiteral serializes a literal data packet to w and returns a +// WriteCloser to which the data itself can be written and which MUST be closed +// on completion. The fileName is truncated to 255 bytes. +func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) { + var buf [4]byte + buf[0] = 't' + if isBinary { + buf[0] = 'b' + } + if len(fileName) > 255 { + fileName = fileName[:255] + } + buf[1] = byte(len(fileName)) + + inner, err := serializeStreamHeader(w, packetTypeLiteralData) + if err != nil { + return + } + + _, err = inner.Write(buf[:2]) + if err != nil { + return + } + _, err = inner.Write([]byte(fileName)) + if err != nil { + return + } + binary.BigEndian.PutUint32(buf[:], time) + _, err = inner.Write(buf[:]) + if err != nil { + return + } + + plaintext = inner + return +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/ocfb.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/ocfb.go new file mode 100644 index 00000000..ce2a33a5 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/ocfb.go @@ -0,0 +1,143 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9 + +package packet + +import ( + "crypto/cipher" +) + +type ocfbEncrypter struct { + b cipher.Block + fre []byte + outUsed int +} + +// An OCFBResyncOption determines if the "resynchronization step" of OCFB is +// performed. +type OCFBResyncOption bool + +const ( + OCFBResync OCFBResyncOption = true + OCFBNoResync OCFBResyncOption = false +) + +// NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's +// cipher feedback mode using the given cipher.Block, and an initial amount of +// ciphertext. randData must be random bytes and be the same length as the +// cipher.Block's block size. Resync determines if the "resynchronization step" +// from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on +// this point. +func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) { + blockSize := block.BlockSize() + if len(randData) != blockSize { + return nil, nil + } + + x := &ocfbEncrypter{ + b: block, + fre: make([]byte, blockSize), + outUsed: 0, + } + prefix := make([]byte, blockSize+2) + + block.Encrypt(x.fre, x.fre) + for i := 0; i < blockSize; i++ { + prefix[i] = randData[i] ^ x.fre[i] + } + + block.Encrypt(x.fre, prefix[:blockSize]) + prefix[blockSize] = x.fre[0] ^ randData[blockSize-2] + prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1] + + if resync { + block.Encrypt(x.fre, prefix[2:]) + } else { + x.fre[0] = prefix[blockSize] + x.fre[1] = prefix[blockSize+1] + x.outUsed = 2 + } + return x, prefix +} + +func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) { + for i := 0; i < len(src); i++ { + if x.outUsed == len(x.fre) { + x.b.Encrypt(x.fre, x.fre) + x.outUsed = 0 + } + + x.fre[x.outUsed] ^= src[i] + dst[i] = x.fre[x.outUsed] + x.outUsed++ + } +} + +type ocfbDecrypter struct { + b cipher.Block + fre []byte + outUsed int +} + +// NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's +// cipher feedback mode using the given cipher.Block. Prefix must be the first +// blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's +// block size. If an incorrect key is detected then nil is returned. On +// successful exit, blockSize+2 bytes of decrypted data are written into +// prefix. Resync determines if the "resynchronization step" from RFC 4880, +// 13.9 step 7 is performed. Different parts of OpenPGP vary on this point. +func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream { + blockSize := block.BlockSize() + if len(prefix) != blockSize+2 { + return nil + } + + x := &ocfbDecrypter{ + b: block, + fre: make([]byte, blockSize), + outUsed: 0, + } + prefixCopy := make([]byte, len(prefix)) + copy(prefixCopy, prefix) + + block.Encrypt(x.fre, x.fre) + for i := 0; i < blockSize; i++ { + prefixCopy[i] ^= x.fre[i] + } + + block.Encrypt(x.fre, prefix[:blockSize]) + prefixCopy[blockSize] ^= x.fre[0] + prefixCopy[blockSize+1] ^= x.fre[1] + + if prefixCopy[blockSize-2] != prefixCopy[blockSize] || + prefixCopy[blockSize-1] != prefixCopy[blockSize+1] { + return nil + } + + if resync { + block.Encrypt(x.fre, prefix[2:]) + } else { + x.fre[0] = prefix[blockSize] + x.fre[1] = prefix[blockSize+1] + x.outUsed = 2 + } + copy(prefix, prefixCopy) + return x +} + +func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) { + for i := 0; i < len(src); i++ { + if x.outUsed == len(x.fre) { + x.b.Encrypt(x.fre, x.fre) + x.outUsed = 0 + } + + c := src[i] + dst[i] = x.fre[x.outUsed] ^ src[i] + x.fre[x.outUsed] = c + x.outUsed++ + } +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/ocfb_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/ocfb_test.go new file mode 100644 index 00000000..91022c04 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/ocfb_test.go @@ -0,0 +1,46 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "crypto/aes" + "crypto/rand" + "testing" +) + +var commonKey128 = []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c} + +func testOCFB(t *testing.T, resync OCFBResyncOption) { + block, err := aes.NewCipher(commonKey128) + if err != nil { + t.Error(err) + return + } + + plaintext := []byte("this is the plaintext, which is long enough to span several blocks.") + randData := make([]byte, block.BlockSize()) + rand.Reader.Read(randData) + ocfb, prefix := NewOCFBEncrypter(block, randData, resync) + ciphertext := make([]byte, len(plaintext)) + ocfb.XORKeyStream(ciphertext, plaintext) + + ocfbdec := NewOCFBDecrypter(block, prefix, resync) + if ocfbdec == nil { + t.Errorf("NewOCFBDecrypter failed (resync: %t)", resync) + return + } + plaintextCopy := make([]byte, len(plaintext)) + ocfbdec.XORKeyStream(plaintextCopy, ciphertext) + + if !bytes.Equal(plaintextCopy, plaintext) { + t.Errorf("got: %x, want: %x (resync: %t)", plaintextCopy, plaintext, resync) + } +} + +func TestOCFB(t *testing.T) { + testOCFB(t, OCFBNoResync) + testOCFB(t, OCFBResync) +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/one_pass_signature.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/one_pass_signature.go new file mode 100644 index 00000000..5240d7e8 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/one_pass_signature.go @@ -0,0 +1,73 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "crypto" + "encoding/binary" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/s2k" + "io" + "strconv" +) + +// OnePassSignature represents a one-pass signature packet. See RFC 4880, +// section 5.4. +type OnePassSignature struct { + SigType SignatureType + Hash crypto.Hash + PubKeyAlgo PublicKeyAlgorithm + KeyId uint64 + IsLast bool +} + +const onePassSignatureVersion = 3 + +func (ops *OnePassSignature) parse(r io.Reader) (err error) { + var buf [13]byte + + _, err = readFull(r, buf[:]) + if err != nil { + return + } + if buf[0] != onePassSignatureVersion { + err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0]))) + } + + var ok bool + ops.Hash, ok = s2k.HashIdToHash(buf[2]) + if !ok { + return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2]))) + } + + ops.SigType = SignatureType(buf[1]) + ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3]) + ops.KeyId = binary.BigEndian.Uint64(buf[4:12]) + ops.IsLast = buf[12] != 0 + return +} + +// Serialize marshals the given OnePassSignature to w. +func (ops *OnePassSignature) Serialize(w io.Writer) error { + var buf [13]byte + buf[0] = onePassSignatureVersion + buf[1] = uint8(ops.SigType) + var ok bool + buf[2], ok = s2k.HashToHashId(ops.Hash) + if !ok { + return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash))) + } + buf[3] = uint8(ops.PubKeyAlgo) + binary.BigEndian.PutUint64(buf[4:12], ops.KeyId) + if ops.IsLast { + buf[12] = 1 + } + + if err := serializeHeader(w, packetTypeOnePassSignature, len(buf)); err != nil { + return err + } + _, err := w.Write(buf[:]) + return err +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/opaque.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/opaque.go new file mode 100644 index 00000000..0b702898 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/opaque.go @@ -0,0 +1,161 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "io" + "io/ioutil" +) + +// OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is +// useful for splitting and storing the original packet contents separately, +// handling unsupported packet types or accessing parts of the packet not yet +// implemented by this package. +type OpaquePacket struct { + // Packet type + Tag uint8 + // Reason why the packet was parsed opaquely + Reason error + // Binary contents of the packet data + Contents []byte +} + +func (op *OpaquePacket) parse(r io.Reader) (err error) { + op.Contents, err = ioutil.ReadAll(r) + return +} + +// Serialize marshals the packet to a writer in its original form, including +// the packet header. +func (op *OpaquePacket) Serialize(w io.Writer) (err error) { + err = serializeHeader(w, packetType(op.Tag), len(op.Contents)) + if err == nil { + _, err = w.Write(op.Contents) + } + return +} + +// Parse attempts to parse the opaque contents into a structure supported by +// this package. If the packet is not known then the result will be another +// OpaquePacket. +func (op *OpaquePacket) Parse() (p Packet, err error) { + hdr := bytes.NewBuffer(nil) + err = serializeHeader(hdr, packetType(op.Tag), len(op.Contents)) + if err != nil { + op.Reason = err + return op, err + } + p, err = Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents))) + if err != nil { + op.Reason = err + p = op + } + return +} + +// OpaqueReader reads OpaquePackets from an io.Reader. +type OpaqueReader struct { + r io.Reader +} + +func NewOpaqueReader(r io.Reader) *OpaqueReader { + return &OpaqueReader{r: r} +} + +// Read the next OpaquePacket. +func (or *OpaqueReader) Next() (op *OpaquePacket, err error) { + tag, _, contents, err := readHeader(or.r) + if err != nil { + return + } + op = &OpaquePacket{Tag: uint8(tag), Reason: err} + err = op.parse(contents) + if err != nil { + consumeAll(contents) + } + return +} + +// OpaqueSubpacket represents an unparsed OpenPGP subpacket, +// as found in signature and user attribute packets. +type OpaqueSubpacket struct { + SubType uint8 + Contents []byte +} + +// OpaqueSubpackets extracts opaque, unparsed OpenPGP subpackets from +// their byte representation. +func OpaqueSubpackets(contents []byte) (result []*OpaqueSubpacket, err error) { + var ( + subHeaderLen int + subPacket *OpaqueSubpacket + ) + for len(contents) > 0 { + subHeaderLen, subPacket, err = nextSubpacket(contents) + if err != nil { + break + } + result = append(result, subPacket) + contents = contents[subHeaderLen+len(subPacket.Contents):] + } + return +} + +func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacket, err error) { + // RFC 4880, section 5.2.3.1 + var subLen uint32 + if len(contents) < 1 { + goto Truncated + } + subPacket = &OpaqueSubpacket{} + switch { + case contents[0] < 192: + subHeaderLen = 2 // 1 length byte, 1 subtype byte + if len(contents) < subHeaderLen { + goto Truncated + } + subLen = uint32(contents[0]) + contents = contents[1:] + case contents[0] < 255: + subHeaderLen = 3 // 2 length bytes, 1 subtype + if len(contents) < subHeaderLen { + goto Truncated + } + subLen = uint32(contents[0]-192)<<8 + uint32(contents[1]) + 192 + contents = contents[2:] + default: + subHeaderLen = 6 // 5 length bytes, 1 subtype + if len(contents) < subHeaderLen { + goto Truncated + } + subLen = uint32(contents[1])<<24 | + uint32(contents[2])<<16 | + uint32(contents[3])<<8 | + uint32(contents[4]) + contents = contents[5:] + } + if subLen > uint32(len(contents)) { + goto Truncated + } + subPacket.SubType = contents[0] + subPacket.Contents = contents[1:subLen] + return +Truncated: + err = errors.StructuralError("subpacket truncated") + return +} + +func (osp *OpaqueSubpacket) Serialize(w io.Writer) (err error) { + buf := make([]byte, 6) + n := serializeSubpacketLength(buf, len(osp.Contents)+1) + buf[n] = osp.SubType + if _, err = w.Write(buf[:n+1]); err != nil { + return + } + _, err = w.Write(osp.Contents) + return +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/opaque_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/opaque_test.go new file mode 100644 index 00000000..f27bbfe0 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/opaque_test.go @@ -0,0 +1,67 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "encoding/hex" + "io" + "testing" +) + +// Test packet.Read error handling in OpaquePacket.Parse, +// which attempts to re-read an OpaquePacket as a supported +// Packet type. +func TestOpaqueParseReason(t *testing.T) { + buf, err := hex.DecodeString(UnsupportedKeyHex) + if err != nil { + t.Fatal(err) + } + or := NewOpaqueReader(bytes.NewBuffer(buf)) + count := 0 + badPackets := 0 + var uid *UserId + for { + op, err := or.Next() + if err == io.EOF { + break + } else if err != nil { + t.Errorf("#%d: opaque read error: %v", count, err) + break + } + // try to parse opaque packet + p, err := op.Parse() + switch pkt := p.(type) { + case *UserId: + uid = pkt + case *OpaquePacket: + // If an OpaquePacket can't re-parse, packet.Read + // certainly had its reasons. + if pkt.Reason == nil { + t.Errorf("#%d: opaque packet, no reason", count) + } else { + badPackets++ + } + } + count++ + } + + const expectedBad = 3 + // Test post-conditions, make sure we actually parsed packets as expected. + if badPackets != expectedBad { + t.Errorf("unexpected # unparseable packets: %d (want %d)", badPackets, expectedBad) + } + if uid == nil { + t.Errorf("failed to find expected UID in unsupported keyring") + } else if uid.Id != "Armin M. Warda " { + t.Errorf("unexpected UID: %v", uid.Id) + } +} + +// This key material has public key and signature packet versions modified to +// an unsupported value (1), so that trying to parse the OpaquePacket to +// a typed packet will get an error. It also contains a GnuPG trust packet. +// (Created with: od -An -t x1 pubring.gpg | xargs | sed 's/ //g') +const UnsupportedKeyHex = `988d012e7a18a20000010400d6ac00d92b89c1f4396c243abb9b76d2e9673ad63483291fed88e22b82e255e441c078c6abbbf7d2d195e50b62eeaa915b85b0ec20c225ce2c64c167cacb6e711daf2e45da4a8356a059b8160e3b3628ac0dd8437b31f06d53d6e8ea4214d4a26406a6b63e1001406ef23e0bb3069fac9a99a91f77dfafd5de0f188a5da5e3c9000511b42741726d696e204d2e205761726461203c7761726461406e657068696c696d2e727568722e64653e8900950105102e8936c705d1eb399e58489901013f0e03ff5a0c4f421e34fcfa388129166420c08cd76987bcdec6f01bd0271459a85cc22048820dd4e44ac2c7d23908d540f54facf1b36b0d9c20488781ce9dca856531e76e2e846826e9951338020a03a09b57aa5faa82e9267458bd76105399885ac35af7dc1cbb6aaed7c39e1039f3b5beda2c0e916bd38560509bab81235d1a0ead83b0020000` diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/packet.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/packet.go new file mode 100644 index 00000000..8c79d99c --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/packet.go @@ -0,0 +1,538 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package packet implements parsing and serialization of OpenPGP packets, as +// specified in RFC 4880. +package packet + +import ( + "bufio" + "crypto/aes" + "crypto/cipher" + "crypto/des" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/cast5" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "io" + "math/big" +) + +// readFull is the same as io.ReadFull except that reading zero bytes returns +// ErrUnexpectedEOF rather than EOF. +func readFull(r io.Reader, buf []byte) (n int, err error) { + n, err = io.ReadFull(r, buf) + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return +} + +// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2. +func readLength(r io.Reader) (length int64, isPartial bool, err error) { + var buf [4]byte + _, err = readFull(r, buf[:1]) + if err != nil { + return + } + switch { + case buf[0] < 192: + length = int64(buf[0]) + case buf[0] < 224: + length = int64(buf[0]-192) << 8 + _, err = readFull(r, buf[0:1]) + if err != nil { + return + } + length += int64(buf[0]) + 192 + case buf[0] < 255: + length = int64(1) << (buf[0] & 0x1f) + isPartial = true + default: + _, err = readFull(r, buf[0:4]) + if err != nil { + return + } + length = int64(buf[0])<<24 | + int64(buf[1])<<16 | + int64(buf[2])<<8 | + int64(buf[3]) + } + return +} + +// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths. +// The continuation lengths are parsed and removed from the stream and EOF is +// returned at the end of the packet. See RFC 4880, section 4.2.2.4. +type partialLengthReader struct { + r io.Reader + remaining int64 + isPartial bool +} + +func (r *partialLengthReader) Read(p []byte) (n int, err error) { + for r.remaining == 0 { + if !r.isPartial { + return 0, io.EOF + } + r.remaining, r.isPartial, err = readLength(r.r) + if err != nil { + return 0, err + } + } + + toRead := int64(len(p)) + if toRead > r.remaining { + toRead = r.remaining + } + + n, err = r.r.Read(p[:int(toRead)]) + r.remaining -= int64(n) + if n < int(toRead) && err == io.EOF { + err = io.ErrUnexpectedEOF + } + return +} + +// partialLengthWriter writes a stream of data using OpenPGP partial lengths. +// See RFC 4880, section 4.2.2.4. +type partialLengthWriter struct { + w io.WriteCloser + lengthByte [1]byte +} + +func (w *partialLengthWriter) Write(p []byte) (n int, err error) { + for len(p) > 0 { + for power := uint(14); power < 32; power-- { + l := 1 << power + if len(p) >= l { + w.lengthByte[0] = 224 + uint8(power) + _, err = w.w.Write(w.lengthByte[:]) + if err != nil { + return + } + var m int + m, err = w.w.Write(p[:l]) + n += m + if err != nil { + return + } + p = p[l:] + break + } + } + } + return +} + +func (w *partialLengthWriter) Close() error { + w.lengthByte[0] = 0 + _, err := w.w.Write(w.lengthByte[:]) + if err != nil { + return err + } + return w.w.Close() +} + +// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the +// underlying Reader returns EOF before the limit has been reached. +type spanReader struct { + r io.Reader + n int64 +} + +func (l *spanReader) Read(p []byte) (n int, err error) { + if l.n <= 0 { + return 0, io.EOF + } + if int64(len(p)) > l.n { + p = p[0:l.n] + } + n, err = l.r.Read(p) + l.n -= int64(n) + if l.n > 0 && err == io.EOF { + err = io.ErrUnexpectedEOF + } + return +} + +// readHeader parses a packet header and returns an io.Reader which will return +// the contents of the packet. See RFC 4880, section 4.2. +func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) { + var buf [4]byte + _, err = io.ReadFull(r, buf[:1]) + if err != nil { + return + } + if buf[0]&0x80 == 0 { + err = errors.StructuralError("tag byte does not have MSB set") + return + } + if buf[0]&0x40 == 0 { + // Old format packet + tag = packetType((buf[0] & 0x3f) >> 2) + lengthType := buf[0] & 3 + if lengthType == 3 { + length = -1 + contents = r + return + } + lengthBytes := 1 << lengthType + _, err = readFull(r, buf[0:lengthBytes]) + if err != nil { + return + } + for i := 0; i < lengthBytes; i++ { + length <<= 8 + length |= int64(buf[i]) + } + contents = &spanReader{r, length} + return + } + + // New format packet + tag = packetType(buf[0] & 0x3f) + length, isPartial, err := readLength(r) + if err != nil { + return + } + if isPartial { + contents = &partialLengthReader{ + remaining: length, + isPartial: true, + r: r, + } + length = -1 + } else { + contents = &spanReader{r, length} + } + return +} + +// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section +// 4.2. +func serializeHeader(w io.Writer, ptype packetType, length int) (err error) { + var buf [6]byte + var n int + + buf[0] = 0x80 | 0x40 | byte(ptype) + if length < 192 { + buf[1] = byte(length) + n = 2 + } else if length < 8384 { + length -= 192 + buf[1] = 192 + byte(length>>8) + buf[2] = byte(length) + n = 3 + } else { + buf[1] = 255 + buf[2] = byte(length >> 24) + buf[3] = byte(length >> 16) + buf[4] = byte(length >> 8) + buf[5] = byte(length) + n = 6 + } + + _, err = w.Write(buf[:n]) + return +} + +// serializeStreamHeader writes an OpenPGP packet header to w where the +// length of the packet is unknown. It returns a io.WriteCloser which can be +// used to write the contents of the packet. See RFC 4880, section 4.2. +func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) { + var buf [1]byte + buf[0] = 0x80 | 0x40 | byte(ptype) + _, err = w.Write(buf[:]) + if err != nil { + return + } + out = &partialLengthWriter{w: w} + return +} + +// Packet represents an OpenPGP packet. Users are expected to try casting +// instances of this interface to specific packet types. +type Packet interface { + parse(io.Reader) error +} + +// consumeAll reads from the given Reader until error, returning the number of +// bytes read. +func consumeAll(r io.Reader) (n int64, err error) { + var m int + var buf [1024]byte + + for { + m, err = r.Read(buf[:]) + n += int64(m) + if err == io.EOF { + err = nil + return + } + if err != nil { + return + } + } + + panic("unreachable") +} + +// packetType represents the numeric ids of the different OpenPGP packet types. See +// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2 +type packetType uint8 + +const ( + packetTypeEncryptedKey packetType = 1 + packetTypeSignature packetType = 2 + packetTypeSymmetricKeyEncrypted packetType = 3 + packetTypeOnePassSignature packetType = 4 + packetTypePrivateKey packetType = 5 + packetTypePublicKey packetType = 6 + packetTypePrivateSubkey packetType = 7 + packetTypeCompressed packetType = 8 + packetTypeSymmetricallyEncrypted packetType = 9 + packetTypeLiteralData packetType = 11 + packetTypeUserId packetType = 13 + packetTypePublicSubkey packetType = 14 + packetTypeUserAttribute packetType = 17 + packetTypeSymmetricallyEncryptedMDC packetType = 18 +) + +// peekVersion detects the version of a public key packet about to +// be read. A bufio.Reader at the original position of the io.Reader +// is returned. +func peekVersion(r io.Reader) (bufr *bufio.Reader, ver byte, err error) { + bufr = bufio.NewReader(r) + var verBuf []byte + if verBuf, err = bufr.Peek(1); err != nil { + return + } + ver = verBuf[0] + return +} + +// Read reads a single OpenPGP packet from the given io.Reader. If there is an +// error parsing a packet, the whole packet is consumed from the input. +func Read(r io.Reader) (p Packet, err error) { + tag, _, contents, err := readHeader(r) + if err != nil { + return + } + + switch tag { + case packetTypeEncryptedKey: + p = new(EncryptedKey) + case packetTypeSignature: + var version byte + // Detect signature version + if contents, version, err = peekVersion(contents); err != nil { + return + } + if version < 4 { + p = new(SignatureV3) + } else { + p = new(Signature) + } + case packetTypeSymmetricKeyEncrypted: + p = new(SymmetricKeyEncrypted) + case packetTypeOnePassSignature: + p = new(OnePassSignature) + case packetTypePrivateKey, packetTypePrivateSubkey: + pk := new(PrivateKey) + if tag == packetTypePrivateSubkey { + pk.IsSubkey = true + } + p = pk + case packetTypePublicKey, packetTypePublicSubkey: + var version byte + if contents, version, err = peekVersion(contents); err != nil { + return + } + isSubkey := tag == packetTypePublicSubkey + if version < 4 { + p = &PublicKeyV3{IsSubkey: isSubkey} + } else { + p = &PublicKey{IsSubkey: isSubkey} + } + case packetTypeCompressed: + p = new(Compressed) + case packetTypeSymmetricallyEncrypted: + p = new(SymmetricallyEncrypted) + case packetTypeLiteralData: + p = new(LiteralData) + case packetTypeUserId: + p = new(UserId) + case packetTypeUserAttribute: + p = new(UserAttribute) + case packetTypeSymmetricallyEncryptedMDC: + se := new(SymmetricallyEncrypted) + se.MDC = true + p = se + default: + err = errors.UnknownPacketTypeError(tag) + } + if p != nil { + err = p.parse(contents) + } + if err != nil { + consumeAll(contents) + } + return +} + +// SignatureType represents the different semantic meanings of an OpenPGP +// signature. See RFC 4880, section 5.2.1. +type SignatureType uint8 + +const ( + SigTypeBinary SignatureType = 0 + SigTypeText = 1 + SigTypeGenericCert = 0x10 + SigTypePersonaCert = 0x11 + SigTypeCasualCert = 0x12 + SigTypePositiveCert = 0x13 + SigTypeSubkeyBinding = 0x18 + SigTypeDirectSignature = 0x1F + SigTypeKeyRevocation = 0x20 + SigTypeSubkeyRevocation = 0x28 +) + +// PublicKeyAlgorithm represents the different public key system specified for +// OpenPGP. See +// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12 +type PublicKeyAlgorithm uint8 + +const ( + PubKeyAlgoRSA PublicKeyAlgorithm = 1 + PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2 + PubKeyAlgoRSASignOnly PublicKeyAlgorithm = 3 + PubKeyAlgoElGamal PublicKeyAlgorithm = 16 + PubKeyAlgoDSA PublicKeyAlgorithm = 17 + // RFC 6637, Section 5. + PubKeyAlgoECDH PublicKeyAlgorithm = 18 + PubKeyAlgoECDSA PublicKeyAlgorithm = 19 +) + +// CanEncrypt returns true if it's possible to encrypt a message to a public +// key of the given type. +func (pka PublicKeyAlgorithm) CanEncrypt() bool { + switch pka { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal: + return true + } + return false +} + +// CanSign returns true if it's possible for a public key of the given type to +// sign a message. +func (pka PublicKeyAlgorithm) CanSign() bool { + switch pka { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: + return true + } + return false +} + +// CipherFunction represents the different block ciphers specified for OpenPGP. See +// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13 +type CipherFunction uint8 + +const ( + Cipher3DES CipherFunction = 2 + CipherCAST5 CipherFunction = 3 + CipherAES128 CipherFunction = 7 + CipherAES192 CipherFunction = 8 + CipherAES256 CipherFunction = 9 +) + +// KeySize returns the key size, in bytes, of cipher. +func (cipher CipherFunction) KeySize() int { + switch cipher { + case Cipher3DES: + return 24 + case CipherCAST5: + return cast5.KeySize + case CipherAES128: + return 16 + case CipherAES192: + return 24 + case CipherAES256: + return 32 + } + return 0 +} + +// blockSize returns the block size, in bytes, of cipher. +func (cipher CipherFunction) blockSize() int { + switch cipher { + case Cipher3DES: + return des.BlockSize + case CipherCAST5: + return 8 + case CipherAES128, CipherAES192, CipherAES256: + return 16 + } + return 0 +} + +// new returns a fresh instance of the given cipher. +func (cipher CipherFunction) new(key []byte) (block cipher.Block) { + switch cipher { + case Cipher3DES: + block, _ = des.NewTripleDESCipher(key) + case CipherCAST5: + block, _ = cast5.NewCipher(key) + case CipherAES128, CipherAES192, CipherAES256: + block, _ = aes.NewCipher(key) + } + return +} + +// readMPI reads a big integer from r. The bit length returned is the bit +// length that was specified in r. This is preserved so that the integer can be +// reserialized exactly. +func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) { + var buf [2]byte + _, err = readFull(r, buf[0:]) + if err != nil { + return + } + bitLength = uint16(buf[0])<<8 | uint16(buf[1]) + numBytes := (int(bitLength) + 7) / 8 + mpi = make([]byte, numBytes) + _, err = readFull(r, mpi) + return +} + +// mpiLength returns the length of the given *big.Int when serialized as an +// MPI. +func mpiLength(n *big.Int) (mpiLengthInBytes int) { + mpiLengthInBytes = 2 /* MPI length */ + mpiLengthInBytes += (n.BitLen() + 7) / 8 + return +} + +// writeMPI serializes a big integer to w. +func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) { + _, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)}) + if err == nil { + _, err = w.Write(mpiBytes) + } + return +} + +// writeBig serializes a *big.Int to w. +func writeBig(w io.Writer, i *big.Int) error { + return writeMPI(w, uint16(i.BitLen()), i.Bytes()) +} + +// CompressionAlgo Represents the different compression algorithms +// supported by OpenPGP (except for BZIP2, which is not currently +// supported). See Section 9.3 of RFC 4880. +type CompressionAlgo uint8 + +const ( + CompressionNone CompressionAlgo = 0 + CompressionZIP CompressionAlgo = 1 + CompressionZLIB CompressionAlgo = 2 +) diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/packet_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/packet_test.go new file mode 100644 index 00000000..33eb8846 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/packet_test.go @@ -0,0 +1,255 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "encoding/hex" + "fmt" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "io" + "io/ioutil" + "testing" +) + +func TestReadFull(t *testing.T) { + var out [4]byte + + b := bytes.NewBufferString("foo") + n, err := readFull(b, out[:3]) + if n != 3 || err != nil { + t.Errorf("full read failed n:%d err:%s", n, err) + } + + b = bytes.NewBufferString("foo") + n, err = readFull(b, out[:4]) + if n != 3 || err != io.ErrUnexpectedEOF { + t.Errorf("partial read failed n:%d err:%s", n, err) + } + + b = bytes.NewBuffer(nil) + n, err = readFull(b, out[:3]) + if n != 0 || err != io.ErrUnexpectedEOF { + t.Errorf("empty read failed n:%d err:%s", n, err) + } +} + +func readerFromHex(s string) io.Reader { + data, err := hex.DecodeString(s) + if err != nil { + panic("readerFromHex: bad input") + } + return bytes.NewBuffer(data) +} + +var readLengthTests = []struct { + hexInput string + length int64 + isPartial bool + err error +}{ + {"", 0, false, io.ErrUnexpectedEOF}, + {"1f", 31, false, nil}, + {"c0", 0, false, io.ErrUnexpectedEOF}, + {"c101", 256 + 1 + 192, false, nil}, + {"e0", 1, true, nil}, + {"e1", 2, true, nil}, + {"e2", 4, true, nil}, + {"ff", 0, false, io.ErrUnexpectedEOF}, + {"ff00", 0, false, io.ErrUnexpectedEOF}, + {"ff0000", 0, false, io.ErrUnexpectedEOF}, + {"ff000000", 0, false, io.ErrUnexpectedEOF}, + {"ff00000000", 0, false, nil}, + {"ff01020304", 16909060, false, nil}, +} + +func TestReadLength(t *testing.T) { + for i, test := range readLengthTests { + length, isPartial, err := readLength(readerFromHex(test.hexInput)) + if test.err != nil { + if err != test.err { + t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err) + } + continue + } + if err != nil { + t.Errorf("%d: unexpected error: %s", i, err) + continue + } + if length != test.length || isPartial != test.isPartial { + t.Errorf("%d: bad result got:(%d,%t) want:(%d,%t)", i, length, isPartial, test.length, test.isPartial) + } + } +} + +var partialLengthReaderTests = []struct { + hexInput string + err error + hexOutput string +}{ + {"e0", io.ErrUnexpectedEOF, ""}, + {"e001", io.ErrUnexpectedEOF, ""}, + {"e0010102", nil, "0102"}, + {"ff00000000", nil, ""}, + {"e10102e1030400", nil, "01020304"}, + {"e101", io.ErrUnexpectedEOF, ""}, +} + +func TestPartialLengthReader(t *testing.T) { + for i, test := range partialLengthReaderTests { + r := &partialLengthReader{readerFromHex(test.hexInput), 0, true} + out, err := ioutil.ReadAll(r) + if test.err != nil { + if err != test.err { + t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err) + } + continue + } + if err != nil { + t.Errorf("%d: unexpected error: %s", i, err) + continue + } + + got := fmt.Sprintf("%x", out) + if got != test.hexOutput { + t.Errorf("%d: got:%s want:%s", i, test.hexOutput, got) + } + } +} + +var readHeaderTests = []struct { + hexInput string + structuralError bool + unexpectedEOF bool + tag int + length int64 + hexOutput string +}{ + {"", false, false, 0, 0, ""}, + {"7f", true, false, 0, 0, ""}, + + // Old format headers + {"80", false, true, 0, 0, ""}, + {"8001", false, true, 0, 1, ""}, + {"800102", false, false, 0, 1, "02"}, + {"81000102", false, false, 0, 1, "02"}, + {"820000000102", false, false, 0, 1, "02"}, + {"860000000102", false, false, 1, 1, "02"}, + {"83010203", false, false, 0, -1, "010203"}, + + // New format headers + {"c0", false, true, 0, 0, ""}, + {"c000", false, false, 0, 0, ""}, + {"c00102", false, false, 0, 1, "02"}, + {"c0020203", false, false, 0, 2, "0203"}, + {"c00202", false, true, 0, 2, ""}, + {"c3020203", false, false, 3, 2, "0203"}, +} + +func TestReadHeader(t *testing.T) { + for i, test := range readHeaderTests { + tag, length, contents, err := readHeader(readerFromHex(test.hexInput)) + if test.structuralError { + if _, ok := err.(errors.StructuralError); ok { + continue + } + t.Errorf("%d: expected StructuralError, got:%s", i, err) + continue + } + if err != nil { + if len(test.hexInput) == 0 && err == io.EOF { + continue + } + if !test.unexpectedEOF || err != io.ErrUnexpectedEOF { + t.Errorf("%d: unexpected error from readHeader: %s", i, err) + } + continue + } + if int(tag) != test.tag || length != test.length { + t.Errorf("%d: got:(%d,%d) want:(%d,%d)", i, int(tag), length, test.tag, test.length) + continue + } + + body, err := ioutil.ReadAll(contents) + if err != nil { + if !test.unexpectedEOF || err != io.ErrUnexpectedEOF { + t.Errorf("%d: unexpected error from contents: %s", i, err) + } + continue + } + if test.unexpectedEOF { + t.Errorf("%d: expected ErrUnexpectedEOF from contents but got no error", i) + continue + } + got := fmt.Sprintf("%x", body) + if got != test.hexOutput { + t.Errorf("%d: got:%s want:%s", i, got, test.hexOutput) + } + } +} + +func TestSerializeHeader(t *testing.T) { + tag := packetTypePublicKey + lengths := []int{0, 1, 2, 64, 192, 193, 8000, 8384, 8385, 10000} + + for _, length := range lengths { + buf := bytes.NewBuffer(nil) + serializeHeader(buf, tag, length) + tag2, length2, _, err := readHeader(buf) + if err != nil { + t.Errorf("length %d, err: %s", length, err) + } + if tag2 != tag { + t.Errorf("length %d, tag incorrect (got %d, want %d)", length, tag2, tag) + } + if int(length2) != length { + t.Errorf("length %d, length incorrect (got %d)", length, length2) + } + } +} + +func TestPartialLengths(t *testing.T) { + buf := bytes.NewBuffer(nil) + w := new(partialLengthWriter) + w.w = noOpCloser{buf} + + const maxChunkSize = 64 + + var b [maxChunkSize]byte + var n uint8 + for l := 1; l <= maxChunkSize; l++ { + for i := 0; i < l; i++ { + b[i] = n + n++ + } + m, err := w.Write(b[:l]) + if m != l { + t.Errorf("short write got: %d want: %d", m, l) + } + if err != nil { + t.Errorf("error from write: %s", err) + } + } + w.Close() + + want := (maxChunkSize * (maxChunkSize + 1)) / 2 + copyBuf := bytes.NewBuffer(nil) + r := &partialLengthReader{buf, 0, true} + m, err := io.Copy(copyBuf, r) + if m != int64(want) { + t.Errorf("short copy got: %d want: %d", m, want) + } + if err != nil { + t.Errorf("error from copy: %s", err) + } + + copyBytes := copyBuf.Bytes() + for i := 0; i < want; i++ { + if copyBytes[i] != uint8(i) { + t.Errorf("bad pattern in copy at %d", i) + break + } + } +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/private_key.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/private_key.go new file mode 100644 index 00000000..bb207fba --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/private_key.go @@ -0,0 +1,310 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "crypto/cipher" + "crypto/dsa" + "crypto/rsa" + "crypto/sha1" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/elgamal" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/s2k" + "io" + "io/ioutil" + "math/big" + "strconv" + "time" +) + +// PrivateKey represents a possibly encrypted private key. See RFC 4880, +// section 5.5.3. +type PrivateKey struct { + PublicKey + Encrypted bool // if true then the private key is unavailable until Decrypt has been called. + encryptedData []byte + cipher CipherFunction + s2k func(out, in []byte) + PrivateKey interface{} // An *rsa.PrivateKey or *dsa.PrivateKey. + sha1Checksum bool + iv []byte +} + +func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey { + pk := new(PrivateKey) + pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey) + pk.PrivateKey = priv + return pk +} + +func NewDSAPrivateKey(currentTime time.Time, priv *dsa.PrivateKey) *PrivateKey { + pk := new(PrivateKey) + pk.PublicKey = *NewDSAPublicKey(currentTime, &priv.PublicKey) + pk.PrivateKey = priv + return pk +} + +func (pk *PrivateKey) parse(r io.Reader) (err error) { + err = (&pk.PublicKey).parse(r) + if err != nil { + return + } + var buf [1]byte + _, err = readFull(r, buf[:]) + if err != nil { + return + } + + s2kType := buf[0] + + switch s2kType { + case 0: + pk.s2k = nil + pk.Encrypted = false + case 254, 255: + _, err = readFull(r, buf[:]) + if err != nil { + return + } + pk.cipher = CipherFunction(buf[0]) + pk.Encrypted = true + pk.s2k, err = s2k.Parse(r) + if err != nil { + return + } + if s2kType == 254 { + pk.sha1Checksum = true + } + default: + return errors.UnsupportedError("deprecated s2k function in private key") + } + + if pk.Encrypted { + blockSize := pk.cipher.blockSize() + if blockSize == 0 { + return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher))) + } + pk.iv = make([]byte, blockSize) + _, err = readFull(r, pk.iv) + if err != nil { + return + } + } + + pk.encryptedData, err = ioutil.ReadAll(r) + if err != nil { + return + } + + if !pk.Encrypted { + return pk.parsePrivateKey(pk.encryptedData) + } + + return +} + +func mod64kHash(d []byte) uint16 { + var h uint16 + for _, b := range d { + h += uint16(b) + } + return h +} + +func (pk *PrivateKey) Serialize(w io.Writer) (err error) { + // TODO(agl): support encrypted private keys + buf := bytes.NewBuffer(nil) + err = pk.PublicKey.serializeWithoutHeaders(buf) + if err != nil { + return + } + buf.WriteByte(0 /* no encryption */) + + privateKeyBuf := bytes.NewBuffer(nil) + + switch priv := pk.PrivateKey.(type) { + case *rsa.PrivateKey: + err = serializeRSAPrivateKey(privateKeyBuf, priv) + case *dsa.PrivateKey: + err = serializeDSAPrivateKey(privateKeyBuf, priv) + default: + err = errors.InvalidArgumentError("unknown private key type") + } + if err != nil { + return + } + + ptype := packetTypePrivateKey + contents := buf.Bytes() + privateKeyBytes := privateKeyBuf.Bytes() + if pk.IsSubkey { + ptype = packetTypePrivateSubkey + } + err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2) + if err != nil { + return + } + _, err = w.Write(contents) + if err != nil { + return + } + _, err = w.Write(privateKeyBytes) + if err != nil { + return + } + + checksum := mod64kHash(privateKeyBytes) + var checksumBytes [2]byte + checksumBytes[0] = byte(checksum >> 8) + checksumBytes[1] = byte(checksum) + _, err = w.Write(checksumBytes[:]) + + return +} + +func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error { + err := writeBig(w, priv.D) + if err != nil { + return err + } + err = writeBig(w, priv.Primes[1]) + if err != nil { + return err + } + err = writeBig(w, priv.Primes[0]) + if err != nil { + return err + } + return writeBig(w, priv.Precomputed.Qinv) +} + +func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error { + return writeBig(w, priv.X) +} + +// Decrypt decrypts an encrypted private key using a passphrase. +func (pk *PrivateKey) Decrypt(passphrase []byte) error { + if !pk.Encrypted { + return nil + } + + key := make([]byte, pk.cipher.KeySize()) + pk.s2k(key, passphrase) + block := pk.cipher.new(key) + cfb := cipher.NewCFBDecrypter(block, pk.iv) + + data := make([]byte, len(pk.encryptedData)) + cfb.XORKeyStream(data, pk.encryptedData) + + if pk.sha1Checksum { + if len(data) < sha1.Size { + return errors.StructuralError("truncated private key data") + } + h := sha1.New() + h.Write(data[:len(data)-sha1.Size]) + sum := h.Sum(nil) + if !bytes.Equal(sum, data[len(data)-sha1.Size:]) { + return errors.StructuralError("private key checksum failure") + } + data = data[:len(data)-sha1.Size] + } else { + if len(data) < 2 { + return errors.StructuralError("truncated private key data") + } + var sum uint16 + for i := 0; i < len(data)-2; i++ { + sum += uint16(data[i]) + } + if data[len(data)-2] != uint8(sum>>8) || + data[len(data)-1] != uint8(sum) { + return errors.StructuralError("private key checksum failure") + } + data = data[:len(data)-2] + } + + return pk.parsePrivateKey(data) +} + +func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) { + switch pk.PublicKey.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly: + return pk.parseRSAPrivateKey(data) + case PubKeyAlgoDSA: + return pk.parseDSAPrivateKey(data) + case PubKeyAlgoElGamal: + return pk.parseElGamalPrivateKey(data) + } + panic("impossible") +} + +func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) { + rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey) + rsaPriv := new(rsa.PrivateKey) + rsaPriv.PublicKey = *rsaPub + + buf := bytes.NewBuffer(data) + d, _, err := readMPI(buf) + if err != nil { + return + } + p, _, err := readMPI(buf) + if err != nil { + return + } + q, _, err := readMPI(buf) + if err != nil { + return + } + + rsaPriv.D = new(big.Int).SetBytes(d) + rsaPriv.Primes = make([]*big.Int, 2) + rsaPriv.Primes[0] = new(big.Int).SetBytes(p) + rsaPriv.Primes[1] = new(big.Int).SetBytes(q) + rsaPriv.Precompute() + pk.PrivateKey = rsaPriv + pk.Encrypted = false + pk.encryptedData = nil + + return nil +} + +func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) { + dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey) + dsaPriv := new(dsa.PrivateKey) + dsaPriv.PublicKey = *dsaPub + + buf := bytes.NewBuffer(data) + x, _, err := readMPI(buf) + if err != nil { + return + } + + dsaPriv.X = new(big.Int).SetBytes(x) + pk.PrivateKey = dsaPriv + pk.Encrypted = false + pk.encryptedData = nil + + return nil +} + +func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) { + pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey) + priv := new(elgamal.PrivateKey) + priv.PublicKey = *pub + + buf := bytes.NewBuffer(data) + x, _, err := readMPI(buf) + if err != nil { + return + } + + priv.X = new(big.Int).SetBytes(x) + pk.PrivateKey = priv + pk.Encrypted = false + pk.encryptedData = nil + + return nil +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/private_key_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/private_key_test.go new file mode 100644 index 00000000..6a6197ae --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/private_key_test.go @@ -0,0 +1,64 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "testing" + "time" +) + +var privateKeyTests = []struct { + privateKeyHex string + creationTime time.Time +}{ + { + privKeyRSAHex, + time.Unix(0x4cc349a8, 0), + }, + { + privKeyElGamalHex, + time.Unix(0x4df9ee1a, 0), + }, +} + +func TestPrivateKeyRead(t *testing.T) { + for i, test := range privateKeyTests { + packet, err := Read(readerFromHex(test.privateKeyHex)) + if err != nil { + t.Errorf("#%d: failed to parse: %s", i, err) + continue + } + + privKey := packet.(*PrivateKey) + + if !privKey.Encrypted { + t.Errorf("#%d: private key isn't encrypted", i) + continue + } + + err = privKey.Decrypt([]byte("wrong password")) + if err == nil { + t.Errorf("#%d: decrypted with incorrect key", i) + continue + } + + err = privKey.Decrypt([]byte("testing")) + if err != nil { + t.Errorf("#%d: failed to decrypt: %s", i, err) + continue + } + + if !privKey.CreationTime.Equal(test.creationTime) || privKey.Encrypted { + t.Errorf("#%d: bad result, got: %#v", i, privKey) + } + } +} + +// Generated with `gpg --export-secret-keys "Test Key 2"` +const privKeyRSAHex = "9501fe044cc349a8010400b70ca0010e98c090008d45d1ee8f9113bd5861fd57b88bacb7c68658747663f1e1a3b5a98f32fda6472373c024b97359cd2efc88ff60f77751adfbf6af5e615e6a1408cfad8bf0cea30b0d5f53aa27ad59089ba9b15b7ebc2777a25d7b436144027e3bcd203909f147d0e332b240cf63d3395f5dfe0df0a6c04e8655af7eacdf0011010001fe0303024a252e7d475fd445607de39a265472aa74a9320ba2dac395faa687e9e0336aeb7e9a7397e511b5afd9dc84557c80ac0f3d4d7bfec5ae16f20d41c8c84a04552a33870b930420e230e179564f6d19bb153145e76c33ae993886c388832b0fa042ddda7f133924f3854481533e0ede31d51278c0519b29abc3bf53da673e13e3e1214b52413d179d7f66deee35cac8eacb060f78379d70ef4af8607e68131ff529439668fc39c9ce6dfef8a5ac234d234802cbfb749a26107db26406213ae5c06d4673253a3cbee1fcbae58d6ab77e38d6e2c0e7c6317c48e054edadb5a40d0d48acb44643d998139a8a66bb820be1f3f80185bc777d14b5954b60effe2448a036d565c6bc0b915fcea518acdd20ab07bc1529f561c58cd044f723109b93f6fd99f876ff891d64306b5d08f48bab59f38695e9109c4dec34013ba3153488ce070268381ba923ee1eb77125b36afcb4347ec3478c8f2735b06ef17351d872e577fa95d0c397c88c71b59629a36aec" + +// Generated by `gpg --export-secret-keys` followed by a manual extraction of +// the ElGamal subkey from the packets. +const privKeyElGamalHex = "9d0157044df9ee1a100400eb8e136a58ec39b582629cdadf830bc64e0a94ed8103ca8bb247b27b11b46d1d25297ef4bcc3071785ba0c0bedfe89eabc5287fcc0edf81ab5896c1c8e4b20d27d79813c7aede75320b33eaeeaa586edc00fd1036c10133e6ba0ff277245d0d59d04b2b3421b7244aca5f4a8d870c6f1c1fbff9e1c26699a860b9504f35ca1d700030503fd1ededd3b840795be6d9ccbe3c51ee42e2f39233c432b831ddd9c4e72b7025a819317e47bf94f9ee316d7273b05d5fcf2999c3a681f519b1234bbfa6d359b4752bd9c3f77d6b6456cde152464763414ca130f4e91d91041432f90620fec0e6d6b5116076c2985d5aeaae13be492b9b329efcaf7ee25120159a0a30cd976b42d7afe030302dae7eb80db744d4960c4df930d57e87fe81412eaace9f900e6c839817a614ddb75ba6603b9417c33ea7b6c93967dfa2bcff3fa3c74a5ce2c962db65b03aece14c96cbd0038fc" diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/public_key.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/public_key.go new file mode 100644 index 00000000..9dfcea7d --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/public_key.go @@ -0,0 +1,687 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "crypto" + "crypto/dsa" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rsa" + "crypto/sha1" + _ "crypto/sha256" + _ "crypto/sha512" + "encoding/binary" + "fmt" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/elgamal" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "hash" + "io" + "math/big" + "strconv" + "time" +) + +var ( + // NIST curve P-256 + oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07} + // NIST curve P-384 + oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22} + // NIST curve P-521 + oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23} +) + +const maxOIDLength = 8 + +// ecdsaKey stores the algorithm-specific fields for ECDSA keys. +// as defined in RFC 6637, Section 9. +type ecdsaKey struct { + // oid contains the OID byte sequence identifying the elliptic curve used + oid []byte + // p contains the elliptic curve point that represents the public key + p parsedMPI +} + +// parseOID reads the OID for the curve as defined in RFC 6637, Section 9. +func parseOID(r io.Reader) (oid []byte, err error) { + buf := make([]byte, maxOIDLength) + if _, err = readFull(r, buf[:1]); err != nil { + return + } + oidLen := buf[0] + if int(oidLen) > len(buf) { + err = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int(oidLen))) + return + } + oid = buf[:oidLen] + _, err = readFull(r, oid) + return +} + +func (f *ecdsaKey) parse(r io.Reader) (err error) { + if f.oid, err = parseOID(r); err != nil { + return err + } + f.p.bytes, f.p.bitLength, err = readMPI(r) + return +} + +func (f *ecdsaKey) serialize(w io.Writer) (err error) { + buf := make([]byte, maxOIDLength+1) + buf[0] = byte(len(f.oid)) + copy(buf[1:], f.oid) + if _, err = w.Write(buf[:len(f.oid)+1]); err != nil { + return + } + return writeMPIs(w, f.p) +} + +func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) { + var c elliptic.Curve + if bytes.Equal(f.oid, oidCurveP256) { + c = elliptic.P256() + } else if bytes.Equal(f.oid, oidCurveP384) { + c = elliptic.P384() + } else if bytes.Equal(f.oid, oidCurveP521) { + c = elliptic.P521() + } else { + return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid)) + } + x, y := elliptic.Unmarshal(c, f.p.bytes) + if x == nil { + return nil, errors.UnsupportedError("failed to parse EC point") + } + return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil +} + +func (f *ecdsaKey) byteLen() int { + return 1 + len(f.oid) + 2 + len(f.p.bytes) +} + +type kdfHashFunction byte +type kdfAlgorithm byte + +// ecdhKdf stores key derivation function parameters +// used for ECDH encryption. See RFC 6637, Section 9. +type ecdhKdf struct { + KdfHash kdfHashFunction + KdfAlgo kdfAlgorithm +} + +func (f *ecdhKdf) parse(r io.Reader) (err error) { + buf := make([]byte, 1) + if _, err = readFull(r, buf); err != nil { + return + } + kdfLen := int(buf[0]) + if kdfLen < 3 { + return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa(kdfLen)) + } + buf = make([]byte, kdfLen) + if _, err = readFull(r, buf); err != nil { + return + } + reserved := int(buf[0]) + f.KdfHash = kdfHashFunction(buf[1]) + f.KdfAlgo = kdfAlgorithm(buf[2]) + if reserved != 0x01 { + return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa(reserved)) + } + return +} + +func (f *ecdhKdf) serialize(w io.Writer) (err error) { + buf := make([]byte, 4) + // See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys. + buf[0] = byte(0x03) // Length of the following fields + buf[1] = byte(0x01) // Reserved for future extensions, must be 1 for now + buf[2] = byte(f.KdfHash) + buf[3] = byte(f.KdfAlgo) + _, err = w.Write(buf[:]) + return +} + +func (f *ecdhKdf) byteLen() int { + return 4 +} + +// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2. +type PublicKey struct { + CreationTime time.Time + PubKeyAlgo PublicKeyAlgorithm + PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey + Fingerprint [20]byte + KeyId uint64 + IsSubkey bool + + n, e, p, q, g, y parsedMPI + + // RFC 6637 fields + ec *ecdsaKey + ecdh *ecdhKdf +} + +// signingKey provides a convenient abstraction over signature verification +// for v3 and v4 public keys. +type signingKey interface { + SerializeSignaturePrefix(io.Writer) + serializeWithoutHeaders(io.Writer) error +} + +func fromBig(n *big.Int) parsedMPI { + return parsedMPI{ + bytes: n.Bytes(), + bitLength: uint16(n.BitLen()), + } +} + +// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey. +func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey { + pk := &PublicKey{ + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoRSA, + PublicKey: pub, + n: fromBig(pub.N), + e: fromBig(big.NewInt(int64(pub.E))), + } + + pk.setFingerPrintAndKeyId() + return pk +} + +// NewDSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey. +func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey { + pk := &PublicKey{ + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoDSA, + PublicKey: pub, + p: fromBig(pub.P), + q: fromBig(pub.Q), + g: fromBig(pub.G), + y: fromBig(pub.Y), + } + + pk.setFingerPrintAndKeyId() + return pk +} + +func (pk *PublicKey) parse(r io.Reader) (err error) { + // RFC 4880, section 5.5.2 + var buf [6]byte + _, err = readFull(r, buf[:]) + if err != nil { + return + } + if buf[0] != 4 { + return errors.UnsupportedError("public key version") + } + pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) + pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5]) + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + err = pk.parseRSA(r) + case PubKeyAlgoDSA: + err = pk.parseDSA(r) + case PubKeyAlgoElGamal: + err = pk.parseElGamal(r) + case PubKeyAlgoECDSA: + pk.ec = new(ecdsaKey) + if err = pk.ec.parse(r); err != nil { + return err + } + pk.PublicKey, err = pk.ec.newECDSA() + case PubKeyAlgoECDH: + pk.ec = new(ecdsaKey) + if err = pk.ec.parse(r); err != nil { + return + } + pk.ecdh = new(ecdhKdf) + if err = pk.ecdh.parse(r); err != nil { + return + } + // The ECDH key is stored in an ecdsa.PublicKey for convenience. + pk.PublicKey, err = pk.ec.newECDSA() + default: + err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) + } + if err != nil { + return + } + + pk.setFingerPrintAndKeyId() + return +} + +func (pk *PublicKey) setFingerPrintAndKeyId() { + // RFC 4880, section 12.2 + fingerPrint := sha1.New() + pk.SerializeSignaturePrefix(fingerPrint) + pk.serializeWithoutHeaders(fingerPrint) + copy(pk.Fingerprint[:], fingerPrint.Sum(nil)) + pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20]) +} + +// parseRSA parses RSA public key material from the given Reader. See RFC 4880, +// section 5.5.2. +func (pk *PublicKey) parseRSA(r io.Reader) (err error) { + pk.n.bytes, pk.n.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.e.bytes, pk.e.bitLength, err = readMPI(r) + if err != nil { + return + } + + if len(pk.e.bytes) > 3 { + err = errors.UnsupportedError("large public exponent") + return + } + rsa := &rsa.PublicKey{ + N: new(big.Int).SetBytes(pk.n.bytes), + E: 0, + } + for i := 0; i < len(pk.e.bytes); i++ { + rsa.E <<= 8 + rsa.E |= int(pk.e.bytes[i]) + } + pk.PublicKey = rsa + return +} + +// parseDSA parses DSA public key material from the given Reader. See RFC 4880, +// section 5.5.2. +func (pk *PublicKey) parseDSA(r io.Reader) (err error) { + pk.p.bytes, pk.p.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.q.bytes, pk.q.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.g.bytes, pk.g.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.y.bytes, pk.y.bitLength, err = readMPI(r) + if err != nil { + return + } + + dsa := new(dsa.PublicKey) + dsa.P = new(big.Int).SetBytes(pk.p.bytes) + dsa.Q = new(big.Int).SetBytes(pk.q.bytes) + dsa.G = new(big.Int).SetBytes(pk.g.bytes) + dsa.Y = new(big.Int).SetBytes(pk.y.bytes) + pk.PublicKey = dsa + return +} + +// parseElGamal parses ElGamal public key material from the given Reader. See +// RFC 4880, section 5.5.2. +func (pk *PublicKey) parseElGamal(r io.Reader) (err error) { + pk.p.bytes, pk.p.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.g.bytes, pk.g.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.y.bytes, pk.y.bitLength, err = readMPI(r) + if err != nil { + return + } + + elgamal := new(elgamal.PublicKey) + elgamal.P = new(big.Int).SetBytes(pk.p.bytes) + elgamal.G = new(big.Int).SetBytes(pk.g.bytes) + elgamal.Y = new(big.Int).SetBytes(pk.y.bytes) + pk.PublicKey = elgamal + return +} + +// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. +// The prefix is used when calculating a signature over this public key. See +// RFC 4880, section 5.2.4. +func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) { + var pLength uint16 + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + pLength += 2 + uint16(len(pk.n.bytes)) + pLength += 2 + uint16(len(pk.e.bytes)) + case PubKeyAlgoDSA: + pLength += 2 + uint16(len(pk.p.bytes)) + pLength += 2 + uint16(len(pk.q.bytes)) + pLength += 2 + uint16(len(pk.g.bytes)) + pLength += 2 + uint16(len(pk.y.bytes)) + case PubKeyAlgoElGamal: + pLength += 2 + uint16(len(pk.p.bytes)) + pLength += 2 + uint16(len(pk.g.bytes)) + pLength += 2 + uint16(len(pk.y.bytes)) + case PubKeyAlgoECDSA: + pLength += uint16(pk.ec.byteLen()) + case PubKeyAlgoECDH: + pLength += uint16(pk.ec.byteLen()) + pLength += uint16(pk.ecdh.byteLen()) + default: + panic("unknown public key algorithm") + } + pLength += 6 + h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) + return +} + +func (pk *PublicKey) Serialize(w io.Writer) (err error) { + length := 6 // 6 byte header + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + length += 2 + len(pk.n.bytes) + length += 2 + len(pk.e.bytes) + case PubKeyAlgoDSA: + length += 2 + len(pk.p.bytes) + length += 2 + len(pk.q.bytes) + length += 2 + len(pk.g.bytes) + length += 2 + len(pk.y.bytes) + case PubKeyAlgoElGamal: + length += 2 + len(pk.p.bytes) + length += 2 + len(pk.g.bytes) + length += 2 + len(pk.y.bytes) + case PubKeyAlgoECDSA: + length += pk.ec.byteLen() + case PubKeyAlgoECDH: + length += pk.ec.byteLen() + length += pk.ecdh.byteLen() + default: + panic("unknown public key algorithm") + } + + packetType := packetTypePublicKey + if pk.IsSubkey { + packetType = packetTypePublicSubkey + } + err = serializeHeader(w, packetType, length) + if err != nil { + return + } + return pk.serializeWithoutHeaders(w) +} + +// serializeWithoutHeaders marshals the PublicKey to w in the form of an +// OpenPGP public key packet, not including the packet header. +func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) { + var buf [6]byte + buf[0] = 4 + t := uint32(pk.CreationTime.Unix()) + buf[1] = byte(t >> 24) + buf[2] = byte(t >> 16) + buf[3] = byte(t >> 8) + buf[4] = byte(t) + buf[5] = byte(pk.PubKeyAlgo) + + _, err = w.Write(buf[:]) + if err != nil { + return + } + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + return writeMPIs(w, pk.n, pk.e) + case PubKeyAlgoDSA: + return writeMPIs(w, pk.p, pk.q, pk.g, pk.y) + case PubKeyAlgoElGamal: + return writeMPIs(w, pk.p, pk.g, pk.y) + case PubKeyAlgoECDSA: + return pk.ec.serialize(w) + case PubKeyAlgoECDH: + if err = pk.ec.serialize(w); err != nil { + return + } + return pk.ecdh.serialize(w) + } + return errors.InvalidArgumentError("bad public-key algorithm") +} + +// CanSign returns true iff this public key can generate signatures +func (pk *PublicKey) CanSign() bool { + return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal +} + +// VerifySignature returns nil iff sig is a valid signature, made by this +// public key, of the data hashed into signed. signed is mutated by this call. +func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) { + if !pk.CanSign() { + return errors.InvalidArgumentError("public key cannot generate signatures") + } + + signed.Write(sig.HashSuffix) + hashBytes := signed.Sum(nil) + + if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { + return errors.SignatureError("hash tag doesn't match") + } + + if pk.PubKeyAlgo != sig.PubKeyAlgo { + return errors.InvalidArgumentError("public key and signature use different algorithms") + } + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey) + err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes) + if err != nil { + return errors.SignatureError("RSA verification failure") + } + return nil + case PubKeyAlgoDSA: + dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey) + // Need to truncate hashBytes to match FIPS 186-3 section 4.6. + subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 + if len(hashBytes) > subgroupSize { + hashBytes = hashBytes[:subgroupSize] + } + if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { + return errors.SignatureError("DSA verification failure") + } + return nil + case PubKeyAlgoECDSA: + ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey) + if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) { + return errors.SignatureError("ECDSA verification failure") + } + return nil + default: + return errors.SignatureError("Unsupported public key algorithm used in signature") + } + panic("unreachable") +} + +// VerifySignatureV3 returns nil iff sig is a valid signature, made by this +// public key, of the data hashed into signed. signed is mutated by this call. +func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { + if !pk.CanSign() { + return errors.InvalidArgumentError("public key cannot generate signatures") + } + + suffix := make([]byte, 5) + suffix[0] = byte(sig.SigType) + binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) + signed.Write(suffix) + hashBytes := signed.Sum(nil) + + if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { + return errors.SignatureError("hash tag doesn't match") + } + + if pk.PubKeyAlgo != sig.PubKeyAlgo { + return errors.InvalidArgumentError("public key and signature use different algorithms") + } + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + rsaPublicKey := pk.PublicKey.(*rsa.PublicKey) + if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil { + return errors.SignatureError("RSA verification failure") + } + return + case PubKeyAlgoDSA: + dsaPublicKey := pk.PublicKey.(*dsa.PublicKey) + // Need to truncate hashBytes to match FIPS 186-3 section 4.6. + subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 + if len(hashBytes) > subgroupSize { + hashBytes = hashBytes[:subgroupSize] + } + if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { + return errors.SignatureError("DSA verification failure") + } + return nil + default: + panic("shouldn't happen") + } + panic("unreachable") +} + +// keySignatureHash returns a Hash of the message that needs to be signed for +// pk to assert a subkey relationship to signed. +func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { + if !hashFunc.Available() { + return nil, errors.UnsupportedError("hash function") + } + h = hashFunc.New() + + // RFC 4880, section 5.2.4 + pk.SerializeSignaturePrefix(h) + pk.serializeWithoutHeaders(h) + signed.SerializeSignaturePrefix(h) + signed.serializeWithoutHeaders(h) + return +} + +// VerifyKeySignature returns nil iff sig is a valid signature, made by this +// public key, of signed. +func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) (err error) { + h, err := keySignatureHash(pk, signed, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignature(h, sig) +} + +func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { + if !hashFunc.Available() { + return nil, errors.UnsupportedError("hash function") + } + h = hashFunc.New() + + // RFC 4880, section 5.2.4 + pk.SerializeSignaturePrefix(h) + pk.serializeWithoutHeaders(h) + + return +} + +// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this +// public key. +func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) { + h, err := keyRevocationHash(pk, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignature(h, sig) +} + +// userIdSignatureHash returns a Hash of the message that needs to be signed +// to assert that pk is a valid key for id. +func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) { + if !hashFunc.Available() { + return nil, errors.UnsupportedError("hash function") + } + h = hashFunc.New() + + // RFC 4880, section 5.2.4 + pk.SerializeSignaturePrefix(h) + pk.serializeWithoutHeaders(h) + + var buf [5]byte + buf[0] = 0xb4 + buf[1] = byte(len(id) >> 24) + buf[2] = byte(len(id) >> 16) + buf[3] = byte(len(id) >> 8) + buf[4] = byte(len(id)) + h.Write(buf[:]) + h.Write([]byte(id)) + + return +} + +// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this +// public key, that id is the identity of pub. +func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) { + h, err := userIdSignatureHash(id, pub, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignature(h, sig) +} + +// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this +// public key, that id is the identity of pub. +func (pk *PublicKey) VerifyUserIdSignatureV3(id string, pub *PublicKey, sig *SignatureV3) (err error) { + h, err := userIdSignatureV3Hash(id, pub, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignatureV3(h, sig) +} + +// KeyIdString returns the public key's fingerprint in capital hex +// (e.g. "6C7EE1B8621CC013"). +func (pk *PublicKey) KeyIdString() string { + return fmt.Sprintf("%X", pk.Fingerprint[12:20]) +} + +// KeyIdShortString returns the short form of public key's fingerprint +// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). +func (pk *PublicKey) KeyIdShortString() string { + return fmt.Sprintf("%X", pk.Fingerprint[16:20]) +} + +// A parsedMPI is used to store the contents of a big integer, along with the +// bit length that was specified in the original input. This allows the MPI to +// be reserialized exactly. +type parsedMPI struct { + bytes []byte + bitLength uint16 +} + +// writeMPIs is a utility function for serializing several big integers to the +// given Writer. +func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) { + for _, mpi := range mpis { + err = writeMPI(w, mpi.bitLength, mpi.bytes) + if err != nil { + return + } + } + return +} + +// BitLength returns the bit length for the given public key. +func (pk *PublicKey) BitLength() (bitLength uint16, err error) { + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + bitLength = pk.n.bitLength + case PubKeyAlgoDSA: + bitLength = pk.p.bitLength + case PubKeyAlgoElGamal: + bitLength = pk.p.bitLength + default: + err = errors.InvalidArgumentError("bad public-key algorithm") + } + return +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/public_key_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/public_key_test.go new file mode 100644 index 00000000..7ad7d918 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/public_key_test.go @@ -0,0 +1,202 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "encoding/hex" + "testing" + "time" +) + +var pubKeyTests = []struct { + hexData string + hexFingerprint string + creationTime time.Time + pubKeyAlgo PublicKeyAlgorithm + keyId uint64 + keyIdString string + keyIdShort string +}{ + {rsaPkDataHex, rsaFingerprintHex, time.Unix(0x4d3c5c10, 0), PubKeyAlgoRSA, 0xa34d7e18c20c31bb, "A34D7E18C20C31BB", "C20C31BB"}, + {dsaPkDataHex, dsaFingerprintHex, time.Unix(0x4d432f89, 0), PubKeyAlgoDSA, 0x8e8fbe54062f19ed, "8E8FBE54062F19ED", "062F19ED"}, + {ecdsaPkDataHex, ecdsaFingerprintHex, time.Unix(0x5071c294, 0), PubKeyAlgoECDSA, 0x43fe956c542ca00b, "43FE956C542CA00B", "542CA00B"}, +} + +func TestPublicKeyRead(t *testing.T) { + for i, test := range pubKeyTests { + packet, err := Read(readerFromHex(test.hexData)) + if err != nil { + t.Errorf("#%d: Read error: %s", i, err) + continue + } + pk, ok := packet.(*PublicKey) + if !ok { + t.Errorf("#%d: failed to parse, got: %#v", i, packet) + continue + } + if pk.PubKeyAlgo != test.pubKeyAlgo { + t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo) + } + if !pk.CreationTime.Equal(test.creationTime) { + t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime) + } + expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint) + if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) { + t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint) + } + if pk.KeyId != test.keyId { + t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId) + } + if g, e := pk.KeyIdString(), test.keyIdString; g != e { + t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e) + } + if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e { + t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e) + } + } +} + +func TestPublicKeySerialize(t *testing.T) { + for i, test := range pubKeyTests { + packet, err := Read(readerFromHex(test.hexData)) + if err != nil { + t.Errorf("#%d: Read error: %s", i, err) + continue + } + pk, ok := packet.(*PublicKey) + if !ok { + t.Errorf("#%d: failed to parse, got: %#v", i, packet) + continue + } + serializeBuf := bytes.NewBuffer(nil) + err = pk.Serialize(serializeBuf) + if err != nil { + t.Errorf("#%d: failed to serialize: %s", i, err) + continue + } + + packet, err = Read(serializeBuf) + if err != nil { + t.Errorf("#%d: Read error (from serialized data): %s", i, err) + continue + } + pk, ok = packet.(*PublicKey) + if !ok { + t.Errorf("#%d: failed to parse serialized data, got: %#v", i, packet) + continue + } + } +} + +func TestEcc384Serialize(t *testing.T) { + r := readerFromHex(ecc384PubHex) + var w bytes.Buffer + for i := 0; i < 2; i++ { + // Public key + p, err := Read(r) + if err != nil { + t.Error(err) + } + pubkey := p.(*PublicKey) + if !bytes.Equal(pubkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) { + t.Errorf("Unexpected pubkey OID: %x", pubkey.ec.oid) + } + if !bytes.Equal(pubkey.ec.p.bytes[:5], []byte{0x04, 0xf6, 0xb8, 0xc5, 0xac}) { + t.Errorf("Unexpected pubkey P[:5]: %x", pubkey.ec.p.bytes) + } + if pubkey.KeyId != 0x098033880F54719F { + t.Errorf("Unexpected pubkey ID: %x", pubkey.KeyId) + } + err = pubkey.Serialize(&w) + if err != nil { + t.Error(err) + } + // User ID + p, err = Read(r) + if err != nil { + t.Error(err) + } + uid := p.(*UserId) + if uid.Id != "ec_dsa_dh_384 " { + t.Error("Unexpected UID:", uid.Id) + } + err = uid.Serialize(&w) + if err != nil { + t.Error(err) + } + // User ID Sig + p, err = Read(r) + if err != nil { + t.Error(err) + } + uidSig := p.(*Signature) + err = pubkey.VerifyUserIdSignature(uid.Id, pubkey, uidSig) + if err != nil { + t.Error(err, ": UID") + } + err = uidSig.Serialize(&w) + if err != nil { + t.Error(err) + } + // Subkey + p, err = Read(r) + if err != nil { + t.Error(err) + } + subkey := p.(*PublicKey) + if !bytes.Equal(subkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) { + t.Errorf("Unexpected subkey OID: %x", subkey.ec.oid) + } + if !bytes.Equal(subkey.ec.p.bytes[:5], []byte{0x04, 0x2f, 0xaa, 0x84, 0x02}) { + t.Errorf("Unexpected subkey P[:5]: %x", subkey.ec.p.bytes) + } + if subkey.ecdh.KdfHash != 0x09 { + t.Error("Expected KDF hash function SHA384 (0x09), got", subkey.ecdh.KdfHash) + } + if subkey.ecdh.KdfAlgo != 0x09 { + t.Error("Expected KDF symmetric alg AES256 (0x09), got", subkey.ecdh.KdfAlgo) + } + if subkey.KeyId != 0xAA8B938F9A201946 { + t.Errorf("Unexpected subkey ID: %x", subkey.KeyId) + } + err = subkey.Serialize(&w) + if err != nil { + t.Error(err) + } + // Subkey Sig + p, err = Read(r) + if err != nil { + t.Error(err) + } + subkeySig := p.(*Signature) + err = pubkey.VerifyKeySignature(subkey, subkeySig) + if err != nil { + t.Error(err) + } + err = subkeySig.Serialize(&w) + if err != nil { + t.Error(err) + } + // Now read back what we've written again + r = bytes.NewBuffer(w.Bytes()) + w.Reset() + } +} + +const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb" + +const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001" + +const dsaFingerprintHex = "eece4c094db002103714c63c8e8fbe54062f19ed" + +const dsaPkDataHex = "9901a2044d432f89110400cd581334f0d7a1e1bdc8b9d6d8c0baf68793632735d2bb0903224cbaa1dfbf35a60ee7a13b92643421e1eb41aa8d79bea19a115a677f6b8ba3c7818ce53a6c2a24a1608bd8b8d6e55c5090cbde09dd26e356267465ae25e69ec8bdd57c7bbb2623e4d73336f73a0a9098f7f16da2e25252130fd694c0e8070c55a812a423ae7f00a0ebf50e70c2f19c3520a551bd4b08d30f23530d3d03ff7d0bf4a53a64a09dc5e6e6e35854b7d70c882b0c60293401958b1bd9e40abec3ea05ba87cf64899299d4bd6aa7f459c201d3fbbd6c82004bdc5e8a9eb8082d12054cc90fa9d4ec251a843236a588bf49552441817436c4f43326966fe85447d4e6d0acf8fa1ef0f014730770603ad7634c3088dc52501c237328417c31c89ed70400b2f1a98b0bf42f11fefc430704bebbaa41d9f355600c3facee1e490f64208e0e094ea55e3a598a219a58500bf78ac677b670a14f4e47e9cf8eab4f368cc1ddcaa18cc59309d4cc62dd4f680e73e6cc3e1ce87a84d0925efbcb26c575c093fc42eecf45135fabf6403a25c2016e1774c0484e440a18319072c617cc97ac0a3bb0" + +const ecdsaFingerprintHex = "9892270b38b8980b05c8d56d43fe956c542ca00b" + +const ecdsaPkDataHex = "9893045071c29413052b8104002304230401f4867769cedfa52c325018896245443968e52e51d0c2df8d939949cb5b330f2921711fbee1c9b9dddb95d15cb0255e99badeddda7cc23d9ddcaacbc290969b9f24019375d61c2e4e3b36953a28d8b2bc95f78c3f1d592fb24499be348656a7b17e3963187b4361afe497bc5f9f81213f04069f8e1fb9e6a6290ae295ca1a92b894396cb4" + +// Source: https://sites.google.com/site/brainhub/pgpecckeys#TOC-ECC-NIST-P-384-key +const ecc384PubHex = `99006f044d53059213052b81040022030304f6b8c5aced5b84ef9f4a209db2e4a9dfb70d28cb8c10ecd57674a9fa5a67389942b62d5e51367df4c7bfd3f8e500feecf07ed265a621a8ebbbe53e947ec78c677eba143bd1533c2b350e1c29f82313e1e1108eba063be1e64b10e6950e799c2db42465635f6473615f64685f333834203c6f70656e70677040627261696e6875622e6f72673e8900cb04101309005305024d530592301480000000002000077072656665727265642d656d61696c2d656e636f64696e67407067702e636f6d7067706d696d65040b090807021901051b03000000021602051e010000000415090a08000a0910098033880f54719fca2b0180aa37350968bd5f115afd8ce7bc7b103822152dbff06d0afcda835329510905b98cb469ba208faab87c7412b799e7b633017f58364ea480e8a1a3f253a0c5f22c446e8be9a9fce6210136ee30811abbd49139de28b5bdf8dc36d06ae748579e9ff503b90073044d53059212052b810400220303042faa84024a20b6735c4897efa5bfb41bf85b7eefeab5ca0cb9ffc8ea04a46acb25534a577694f9e25340a4ab5223a9dd1eda530c8aa2e6718db10d7e672558c7736fe09369ea5739a2a3554bf16d41faa50562f11c6d39bbd5dffb6b9a9ec9180301090989008404181309000c05024d530592051b0c000000000a0910098033880f54719f80970180eee7a6d8fcee41ee4f9289df17f9bcf9d955dca25c583b94336f3a2b2d4986dc5cf417b8d2dc86f741a9e1a6d236c0e3017d1c76575458a0cfb93ae8a2b274fcc65ceecd7a91eec83656ba13219969f06945b48c56bd04152c3a0553c5f2f4bd1267` diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/public_key_v3.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/public_key_v3.go new file mode 100644 index 00000000..3c7c9e3c --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/public_key_v3.go @@ -0,0 +1,275 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "crypto" + "crypto/md5" + "crypto/rsa" + "encoding/binary" + "fmt" + "hash" + "io" + "math/big" + "strconv" + "time" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" +) + +// PublicKeyV3 represents older, version 3 public keys. These keys are less secure and +// should not be used for signing or encrypting. They are supported here only for +// parsing version 3 key material and validating signatures. +// See RFC 4880, section 5.5.2. +type PublicKeyV3 struct { + CreationTime time.Time + DaysToExpire uint16 + PubKeyAlgo PublicKeyAlgorithm + PublicKey *rsa.PublicKey + Fingerprint [16]byte + KeyId uint64 + IsSubkey bool + + n, e parsedMPI +} + +// newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey. +// Included here for testing purposes only. RFC 4880, section 5.5.2: +// "an implementation MUST NOT generate a V3 key, but MAY accept it." +func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 { + pk := &PublicKeyV3{ + CreationTime: creationTime, + PublicKey: pub, + n: fromBig(pub.N), + e: fromBig(big.NewInt(int64(pub.E))), + } + + pk.setFingerPrintAndKeyId() + return pk +} + +func (pk *PublicKeyV3) parse(r io.Reader) (err error) { + // RFC 4880, section 5.5.2 + var buf [8]byte + if _, err = readFull(r, buf[:]); err != nil { + return + } + if buf[0] < 2 || buf[0] > 3 { + return errors.UnsupportedError("public key version") + } + pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) + pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7]) + pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7]) + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + err = pk.parseRSA(r) + default: + err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) + } + if err != nil { + return + } + + pk.setFingerPrintAndKeyId() + return +} + +func (pk *PublicKeyV3) setFingerPrintAndKeyId() { + // RFC 4880, section 12.2 + fingerPrint := md5.New() + fingerPrint.Write(pk.n.bytes) + fingerPrint.Write(pk.e.bytes) + fingerPrint.Sum(pk.Fingerprint[:0]) + pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:]) +} + +// parseRSA parses RSA public key material from the given Reader. See RFC 4880, +// section 5.5.2. +func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) { + if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil { + return + } + if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil { + return + } + + if len(pk.e.bytes) > 3 { + err = errors.UnsupportedError("large public exponent") + return + } + rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)} + for i := 0; i < len(pk.e.bytes); i++ { + rsa.E <<= 8 + rsa.E |= int(pk.e.bytes[i]) + } + pk.PublicKey = rsa + return +} + +// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. +// The prefix is used when calculating a signature over this public key. See +// RFC 4880, section 5.2.4. +func (pk *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) { + var pLength uint16 + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + pLength += 2 + uint16(len(pk.n.bytes)) + pLength += 2 + uint16(len(pk.e.bytes)) + default: + panic("unknown public key algorithm") + } + pLength += 6 + w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) + return +} + +func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) { + length := 8 // 8 byte header + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + length += 2 + len(pk.n.bytes) + length += 2 + len(pk.e.bytes) + default: + panic("unknown public key algorithm") + } + + packetType := packetTypePublicKey + if pk.IsSubkey { + packetType = packetTypePublicSubkey + } + if err = serializeHeader(w, packetType, length); err != nil { + return + } + return pk.serializeWithoutHeaders(w) +} + +// serializeWithoutHeaders marshals the PublicKey to w in the form of an +// OpenPGP public key packet, not including the packet header. +func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) { + var buf [8]byte + // Version 3 + buf[0] = 3 + // Creation time + t := uint32(pk.CreationTime.Unix()) + buf[1] = byte(t >> 24) + buf[2] = byte(t >> 16) + buf[3] = byte(t >> 8) + buf[4] = byte(t) + // Days to expire + buf[5] = byte(pk.DaysToExpire >> 8) + buf[6] = byte(pk.DaysToExpire) + // Public key algorithm + buf[7] = byte(pk.PubKeyAlgo) + + if _, err = w.Write(buf[:]); err != nil { + return + } + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + return writeMPIs(w, pk.n, pk.e) + } + return errors.InvalidArgumentError("bad public-key algorithm") +} + +// CanSign returns true iff this public key can generate signatures +func (pk *PublicKeyV3) CanSign() bool { + return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly +} + +// VerifySignatureV3 returns nil iff sig is a valid signature, made by this +// public key, of the data hashed into signed. signed is mutated by this call. +func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { + if !pk.CanSign() { + return errors.InvalidArgumentError("public key cannot generate signatures") + } + + suffix := make([]byte, 5) + suffix[0] = byte(sig.SigType) + binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) + signed.Write(suffix) + hashBytes := signed.Sum(nil) + + if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { + return errors.SignatureError("hash tag doesn't match") + } + + if pk.PubKeyAlgo != sig.PubKeyAlgo { + return errors.InvalidArgumentError("public key and signature use different algorithms") + } + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil { + return errors.SignatureError("RSA verification failure") + } + return + default: + // V3 public keys only support RSA. + panic("shouldn't happen") + } + panic("unreachable") +} + +// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this +// public key, that id is the identity of pub. +func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) { + h, err := userIdSignatureV3Hash(id, pk, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignatureV3(h, sig) +} + +// VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this +// public key, of signed. +func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) { + h, err := keySignatureHash(pk, signed, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignatureV3(h, sig) +} + +// userIdSignatureV3Hash returns a Hash of the message that needs to be signed +// to assert that pk is a valid key for id. +func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) { + if !hfn.Available() { + return nil, errors.UnsupportedError("hash function") + } + h = hfn.New() + + // RFC 4880, section 5.2.4 + pk.SerializeSignaturePrefix(h) + pk.serializeWithoutHeaders(h) + + h.Write([]byte(id)) + + return +} + +// KeyIdString returns the public key's fingerprint in capital hex +// (e.g. "6C7EE1B8621CC013"). +func (pk *PublicKeyV3) KeyIdString() string { + return fmt.Sprintf("%X", pk.KeyId) +} + +// KeyIdShortString returns the short form of public key's fingerprint +// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). +func (pk *PublicKeyV3) KeyIdShortString() string { + return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF) +} + +// BitLength returns the bit length for the given public key. +func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) { + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + bitLength = pk.n.bitLength + default: + err = errors.InvalidArgumentError("bad public-key algorithm") + } + return +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go new file mode 100644 index 00000000..e0640590 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go @@ -0,0 +1,82 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "encoding/hex" + "testing" + "time" +) + +var pubKeyV3Test = struct { + hexFingerprint string + creationTime time.Time + pubKeyAlgo PublicKeyAlgorithm + keyId uint64 + keyIdString string + keyIdShort string +}{ + "103BECF5BD1E837C89D19E98487767F7", + time.Unix(779753634, 0), + PubKeyAlgoRSA, + 0xDE0F188A5DA5E3C9, + "DE0F188A5DA5E3C9", + "5DA5E3C9"} + +func TestPublicKeyV3Read(t *testing.T) { + i, test := 0, pubKeyV3Test + packet, err := Read(v3KeyReader(t)) + if err != nil { + t.Fatalf("#%d: Read error: %s", i, err) + } + pk, ok := packet.(*PublicKeyV3) + if !ok { + t.Fatalf("#%d: failed to parse, got: %#v", i, packet) + } + if pk.PubKeyAlgo != test.pubKeyAlgo { + t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo) + } + if !pk.CreationTime.Equal(test.creationTime) { + t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime) + } + expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint) + if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) { + t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint) + } + if pk.KeyId != test.keyId { + t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId) + } + if g, e := pk.KeyIdString(), test.keyIdString; g != e { + t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e) + } + if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e { + t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e) + } +} + +func TestPublicKeyV3Serialize(t *testing.T) { + //for i, test := range pubKeyV3Tests { + i := 0 + packet, err := Read(v3KeyReader(t)) + if err != nil { + t.Fatalf("#%d: Read error: %s", i, err) + } + pk, ok := packet.(*PublicKeyV3) + if !ok { + t.Fatalf("#%d: failed to parse, got: %#v", i, packet) + } + var serializeBuf bytes.Buffer + if err = pk.Serialize(&serializeBuf); err != nil { + t.Fatalf("#%d: failed to serialize: %s", i, err) + } + + if packet, err = Read(bytes.NewBuffer(serializeBuf.Bytes())); err != nil { + t.Fatalf("#%d: Read error (from serialized data): %s", i, err) + } + if pk, ok = packet.(*PublicKeyV3); !ok { + t.Fatalf("#%d: failed to parse serialized data, got: %#v", i, packet) + } +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/reader.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/reader.go new file mode 100644 index 00000000..078a89ed --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/reader.go @@ -0,0 +1,76 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "io" +) + +// Reader reads packets from an io.Reader and allows packets to be 'unread' so +// that they result from the next call to Next. +type Reader struct { + q []Packet + readers []io.Reader +} + +// New io.Readers are pushed when a compressed or encrypted packet is processed +// and recursively treated as a new source of packets. However, a carefully +// crafted packet can trigger an infinite recursive sequence of packets. See +// http://mumble.net/~campbell/misc/pgp-quine +// https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4402 +// This constant limits the number of recursive packets that may be pushed. +const maxReaders = 32 + +// Next returns the most recently unread Packet, or reads another packet from +// the top-most io.Reader. Unknown packet types are skipped. +func (r *Reader) Next() (p Packet, err error) { + if len(r.q) > 0 { + p = r.q[len(r.q)-1] + r.q = r.q[:len(r.q)-1] + return + } + + for len(r.readers) > 0 { + p, err = Read(r.readers[len(r.readers)-1]) + if err == nil { + return + } + if err == io.EOF { + r.readers = r.readers[:len(r.readers)-1] + continue + } + if _, ok := err.(errors.UnknownPacketTypeError); !ok { + return nil, err + } + } + + return nil, io.EOF +} + +// Push causes the Reader to start reading from a new io.Reader. When an EOF +// error is seen from the new io.Reader, it is popped and the Reader continues +// to read from the next most recent io.Reader. Push returns a StructuralError +// if pushing the reader would exceed the maximum recursion level, otherwise it +// returns nil. +func (r *Reader) Push(reader io.Reader) (err error) { + if len(r.readers) >= maxReaders { + return errors.StructuralError("too many layers of packets") + } + r.readers = append(r.readers, reader) + return nil +} + +// Unread causes the given Packet to be returned from the next call to Next. +func (r *Reader) Unread(p Packet) { + r.q = append(r.q, p) +} + +func NewReader(r io.Reader) *Reader { + return &Reader{ + q: nil, + readers: []io.Reader{r}, + } +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/signature.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/signature.go new file mode 100644 index 00000000..d87705ae --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/signature.go @@ -0,0 +1,674 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "crypto" + "crypto/dsa" + "crypto/rsa" + "encoding/binary" + "hash" + "io" + "strconv" + "time" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/s2k" +) + +const ( + // See RFC 4880, section 5.2.3.21 for details. + KeyFlagCertify = 1 << iota + KeyFlagSign + KeyFlagEncryptCommunications + KeyFlagEncryptStorage +) + +// Signature represents a signature. See RFC 4880, section 5.2. +type Signature struct { + SigType SignatureType + PubKeyAlgo PublicKeyAlgorithm + Hash crypto.Hash + + // HashSuffix is extra data that is hashed in after the signed data. + HashSuffix []byte + // HashTag contains the first two bytes of the hash for fast rejection + // of bad signed data. + HashTag [2]byte + CreationTime time.Time + + RSASignature parsedMPI + DSASigR, DSASigS parsedMPI + ECDSASigR, ECDSASigS parsedMPI + + // rawSubpackets contains the unparsed subpackets, in order. + rawSubpackets []outputSubpacket + + // The following are optional so are nil when not included in the + // signature. + + SigLifetimeSecs, KeyLifetimeSecs *uint32 + PreferredSymmetric, PreferredHash, PreferredCompression []uint8 + IssuerKeyId *uint64 + IsPrimaryId *bool + + // FlagsValid is set if any flags were given. See RFC 4880, section + // 5.2.3.21 for details. + FlagsValid bool + FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool + + // RevocationReason is set if this signature has been revoked. + // See RFC 4880, section 5.2.3.23 for details. + RevocationReason *uint8 + RevocationReasonText string + + // MDC is set if this signature has a feature packet that indicates + // support for MDC subpackets. + MDC bool + + outSubpackets []outputSubpacket +} + +func (sig *Signature) parse(r io.Reader) (err error) { + // RFC 4880, section 5.2.3 + var buf [5]byte + _, err = readFull(r, buf[:1]) + if err != nil { + return + } + if buf[0] != 4 { + err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) + return + } + + _, err = readFull(r, buf[:5]) + if err != nil { + return + } + sig.SigType = SignatureType(buf[0]) + sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1]) + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: + default: + err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) + return + } + + var ok bool + sig.Hash, ok = s2k.HashIdToHash(buf[2]) + if !ok { + return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) + } + + hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4]) + l := 6 + hashedSubpacketsLength + sig.HashSuffix = make([]byte, l+6) + sig.HashSuffix[0] = 4 + copy(sig.HashSuffix[1:], buf[:5]) + hashedSubpackets := sig.HashSuffix[6:l] + _, err = readFull(r, hashedSubpackets) + if err != nil { + return + } + // See RFC 4880, section 5.2.4 + trailer := sig.HashSuffix[l:] + trailer[0] = 4 + trailer[1] = 0xff + trailer[2] = uint8(l >> 24) + trailer[3] = uint8(l >> 16) + trailer[4] = uint8(l >> 8) + trailer[5] = uint8(l) + + err = parseSignatureSubpackets(sig, hashedSubpackets, true) + if err != nil { + return + } + + _, err = readFull(r, buf[:2]) + if err != nil { + return + } + unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1]) + unhashedSubpackets := make([]byte, unhashedSubpacketsLength) + _, err = readFull(r, unhashedSubpackets) + if err != nil { + return + } + err = parseSignatureSubpackets(sig, unhashedSubpackets, false) + if err != nil { + return + } + + _, err = readFull(r, sig.HashTag[:2]) + if err != nil { + return + } + + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) + case PubKeyAlgoDSA: + sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r) + if err == nil { + sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) + } + case PubKeyAlgoECDSA: + sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r) + if err == nil { + sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r) + } + default: + panic("unreachable") + } + return +} + +// parseSignatureSubpackets parses subpackets of the main signature packet. See +// RFC 4880, section 5.2.3.1. +func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) { + for len(subpackets) > 0 { + subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed) + if err != nil { + return + } + } + + if sig.CreationTime.IsZero() { + err = errors.StructuralError("no creation time in signature") + } + + return +} + +type signatureSubpacketType uint8 + +const ( + creationTimeSubpacket signatureSubpacketType = 2 + signatureExpirationSubpacket signatureSubpacketType = 3 + keyExpirationSubpacket signatureSubpacketType = 9 + prefSymmetricAlgosSubpacket signatureSubpacketType = 11 + issuerSubpacket signatureSubpacketType = 16 + prefHashAlgosSubpacket signatureSubpacketType = 21 + prefCompressionSubpacket signatureSubpacketType = 22 + primaryUserIdSubpacket signatureSubpacketType = 25 + keyFlagsSubpacket signatureSubpacketType = 27 + reasonForRevocationSubpacket signatureSubpacketType = 29 + featuresSubpacket signatureSubpacketType = 30 +) + +// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1. +func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) { + // RFC 4880, section 5.2.3.1 + var ( + length uint32 + packetType signatureSubpacketType + isCritical bool + ) + switch { + case subpacket[0] < 192: + length = uint32(subpacket[0]) + subpacket = subpacket[1:] + case subpacket[0] < 255: + if len(subpacket) < 2 { + goto Truncated + } + length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192 + subpacket = subpacket[2:] + default: + if len(subpacket) < 5 { + goto Truncated + } + length = uint32(subpacket[1])<<24 | + uint32(subpacket[2])<<16 | + uint32(subpacket[3])<<8 | + uint32(subpacket[4]) + subpacket = subpacket[5:] + } + if length > uint32(len(subpacket)) { + goto Truncated + } + rest = subpacket[length:] + subpacket = subpacket[:length] + if len(subpacket) == 0 { + err = errors.StructuralError("zero length signature subpacket") + return + } + packetType = signatureSubpacketType(subpacket[0] & 0x7f) + isCritical = subpacket[0]&0x80 == 0x80 + subpacket = subpacket[1:] + sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket}) + switch packetType { + case creationTimeSubpacket: + if !isHashed { + err = errors.StructuralError("signature creation time in non-hashed area") + return + } + if len(subpacket) != 4 { + err = errors.StructuralError("signature creation time not four bytes") + return + } + t := binary.BigEndian.Uint32(subpacket) + sig.CreationTime = time.Unix(int64(t), 0) + case signatureExpirationSubpacket: + // Signature expiration time, section 5.2.3.10 + if !isHashed { + return + } + if len(subpacket) != 4 { + err = errors.StructuralError("expiration subpacket with bad length") + return + } + sig.SigLifetimeSecs = new(uint32) + *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket) + case keyExpirationSubpacket: + // Key expiration time, section 5.2.3.6 + if !isHashed { + return + } + if len(subpacket) != 4 { + err = errors.StructuralError("key expiration subpacket with bad length") + return + } + sig.KeyLifetimeSecs = new(uint32) + *sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket) + case prefSymmetricAlgosSubpacket: + // Preferred symmetric algorithms, section 5.2.3.7 + if !isHashed { + return + } + sig.PreferredSymmetric = make([]byte, len(subpacket)) + copy(sig.PreferredSymmetric, subpacket) + case issuerSubpacket: + // Issuer, section 5.2.3.5 + if len(subpacket) != 8 { + err = errors.StructuralError("issuer subpacket with bad length") + return + } + sig.IssuerKeyId = new(uint64) + *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket) + case prefHashAlgosSubpacket: + // Preferred hash algorithms, section 5.2.3.8 + if !isHashed { + return + } + sig.PreferredHash = make([]byte, len(subpacket)) + copy(sig.PreferredHash, subpacket) + case prefCompressionSubpacket: + // Preferred compression algorithms, section 5.2.3.9 + if !isHashed { + return + } + sig.PreferredCompression = make([]byte, len(subpacket)) + copy(sig.PreferredCompression, subpacket) + case primaryUserIdSubpacket: + // Primary User ID, section 5.2.3.19 + if !isHashed { + return + } + if len(subpacket) != 1 { + err = errors.StructuralError("primary user id subpacket with bad length") + return + } + sig.IsPrimaryId = new(bool) + if subpacket[0] > 0 { + *sig.IsPrimaryId = true + } + case keyFlagsSubpacket: + // Key flags, section 5.2.3.21 + if !isHashed { + return + } + if len(subpacket) == 0 { + err = errors.StructuralError("empty key flags subpacket") + return + } + sig.FlagsValid = true + if subpacket[0]&KeyFlagCertify != 0 { + sig.FlagCertify = true + } + if subpacket[0]&KeyFlagSign != 0 { + sig.FlagSign = true + } + if subpacket[0]&KeyFlagEncryptCommunications != 0 { + sig.FlagEncryptCommunications = true + } + if subpacket[0]&KeyFlagEncryptStorage != 0 { + sig.FlagEncryptStorage = true + } + case reasonForRevocationSubpacket: + // Reason For Revocation, section 5.2.3.23 + if !isHashed { + return + } + if len(subpacket) == 0 { + err = errors.StructuralError("empty revocation reason subpacket") + return + } + sig.RevocationReason = new(uint8) + *sig.RevocationReason = subpacket[0] + sig.RevocationReasonText = string(subpacket[1:]) + case featuresSubpacket: + // Features subpacket, section 5.2.3.24 specifies a very general + // mechanism for OpenPGP implementations to signal support for new + // features. In practice, the subpacket is used exclusively to + // indicate support for MDC-protected encryption. + sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1 + default: + if isCritical { + err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType))) + return + } + } + return + +Truncated: + err = errors.StructuralError("signature subpacket truncated") + return +} + +// subpacketLengthLength returns the length, in bytes, of an encoded length value. +func subpacketLengthLength(length int) int { + if length < 192 { + return 1 + } + if length < 16320 { + return 2 + } + return 5 +} + +// serializeSubpacketLength marshals the given length into to. +func serializeSubpacketLength(to []byte, length int) int { + // RFC 4880, Section 4.2.2. + if length < 192 { + to[0] = byte(length) + return 1 + } + if length < 16320 { + length -= 192 + to[0] = byte((length >> 8) + 192) + to[1] = byte(length) + return 2 + } + to[0] = 255 + to[1] = byte(length >> 24) + to[2] = byte(length >> 16) + to[3] = byte(length >> 8) + to[4] = byte(length) + return 5 +} + +// subpacketsLength returns the serialized length, in bytes, of the given +// subpackets. +func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) { + for _, subpacket := range subpackets { + if subpacket.hashed == hashed { + length += subpacketLengthLength(len(subpacket.contents) + 1) + length += 1 // type byte + length += len(subpacket.contents) + } + } + return +} + +// serializeSubpackets marshals the given subpackets into to. +func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) { + for _, subpacket := range subpackets { + if subpacket.hashed == hashed { + n := serializeSubpacketLength(to, len(subpacket.contents)+1) + to[n] = byte(subpacket.subpacketType) + to = to[1+n:] + n = copy(to, subpacket.contents) + to = to[n:] + } + } + return +} + +// KeyExpired returns whether sig is a self-signature of a key that has +// expired. +func (sig *Signature) KeyExpired(currentTime time.Time) bool { + if sig.KeyLifetimeSecs == nil { + return false + } + expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second) + return currentTime.After(expiry) +} + +// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing. +func (sig *Signature) buildHashSuffix() (err error) { + hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true) + + var ok bool + l := 6 + hashedSubpacketsLen + sig.HashSuffix = make([]byte, l+6) + sig.HashSuffix[0] = 4 + sig.HashSuffix[1] = uint8(sig.SigType) + sig.HashSuffix[2] = uint8(sig.PubKeyAlgo) + sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash) + if !ok { + sig.HashSuffix = nil + return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash))) + } + sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8) + sig.HashSuffix[5] = byte(hashedSubpacketsLen) + serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true) + trailer := sig.HashSuffix[l:] + trailer[0] = 4 + trailer[1] = 0xff + trailer[2] = byte(l >> 24) + trailer[3] = byte(l >> 16) + trailer[4] = byte(l >> 8) + trailer[5] = byte(l) + return +} + +func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) { + err = sig.buildHashSuffix() + if err != nil { + return + } + + h.Write(sig.HashSuffix) + digest = h.Sum(nil) + copy(sig.HashTag[:], digest) + return +} + +// Sign signs a message with a private key. The hash, h, must contain +// the hash of the message to be signed and will be mutated by this function. +// On success, the signature is stored in sig. Call Serialize to write it out. +// If config is nil, sensible defaults will be used. +func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) { + sig.outSubpackets = sig.buildSubpackets() + digest, err := sig.signPrepareHash(h) + if err != nil { + return + } + + switch priv.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + sig.RSASignature.bytes, err = rsa.SignPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest) + sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes)) + case PubKeyAlgoDSA: + dsaPriv := priv.PrivateKey.(*dsa.PrivateKey) + + // Need to truncate hashBytes to match FIPS 186-3 section 4.6. + subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8 + if len(digest) > subgroupSize { + digest = digest[:subgroupSize] + } + r, s, err := dsa.Sign(config.Random(), dsaPriv, digest) + if err == nil { + sig.DSASigR.bytes = r.Bytes() + sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes)) + sig.DSASigS.bytes = s.Bytes() + sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes)) + } + default: + err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo))) + } + + return +} + +// SignUserId computes a signature from priv, asserting that pub is a valid +// key for the identity id. On success, the signature is stored in sig. Call +// Serialize to write it out. +// If config is nil, sensible defaults will be used. +func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error { + h, err := userIdSignatureHash(id, pub, sig.Hash) + if err != nil { + return nil + } + return sig.Sign(h, priv, config) +} + +// SignKey computes a signature from priv, asserting that pub is a subkey. On +// success, the signature is stored in sig. Call Serialize to write it out. +// If config is nil, sensible defaults will be used. +func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error { + h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash) + if err != nil { + return err + } + return sig.Sign(h, priv, config) +} + +// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been +// called first. +func (sig *Signature) Serialize(w io.Writer) (err error) { + if len(sig.outSubpackets) == 0 { + sig.outSubpackets = sig.rawSubpackets + } + if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil { + return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") + } + + sigLength := 0 + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + sigLength = 2 + len(sig.RSASignature.bytes) + case PubKeyAlgoDSA: + sigLength = 2 + len(sig.DSASigR.bytes) + sigLength += 2 + len(sig.DSASigS.bytes) + case PubKeyAlgoECDSA: + sigLength = 2 + len(sig.ECDSASigR.bytes) + sigLength += 2 + len(sig.ECDSASigS.bytes) + default: + panic("impossible") + } + + unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false) + length := len(sig.HashSuffix) - 6 /* trailer not included */ + + 2 /* length of unhashed subpackets */ + unhashedSubpacketsLen + + 2 /* hash tag */ + sigLength + err = serializeHeader(w, packetTypeSignature, length) + if err != nil { + return + } + + _, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6]) + if err != nil { + return + } + + unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen) + unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8) + unhashedSubpackets[1] = byte(unhashedSubpacketsLen) + serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false) + + _, err = w.Write(unhashedSubpackets) + if err != nil { + return + } + _, err = w.Write(sig.HashTag[:]) + if err != nil { + return + } + + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + err = writeMPIs(w, sig.RSASignature) + case PubKeyAlgoDSA: + err = writeMPIs(w, sig.DSASigR, sig.DSASigS) + case PubKeyAlgoECDSA: + err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS) + default: + panic("impossible") + } + return +} + +// outputSubpacket represents a subpacket to be marshaled. +type outputSubpacket struct { + hashed bool // true if this subpacket is in the hashed area. + subpacketType signatureSubpacketType + isCritical bool + contents []byte +} + +func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) { + creationTime := make([]byte, 4) + binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix())) + subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime}) + + if sig.IssuerKeyId != nil { + keyId := make([]byte, 8) + binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId) + subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId}) + } + + if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 { + sigLifetime := make([]byte, 4) + binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs) + subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime}) + } + + // Key flags may only appear in self-signatures or certification signatures. + + if sig.FlagsValid { + var flags byte + if sig.FlagCertify { + flags |= KeyFlagCertify + } + if sig.FlagSign { + flags |= KeyFlagSign + } + if sig.FlagEncryptCommunications { + flags |= KeyFlagEncryptCommunications + } + if sig.FlagEncryptStorage { + flags |= KeyFlagEncryptStorage + } + subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}}) + } + + // The following subpackets may only appear in self-signatures + + if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 { + keyLifetime := make([]byte, 4) + binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs) + subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime}) + } + + if sig.IsPrimaryId != nil && *sig.IsPrimaryId { + subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}}) + } + + if len(sig.PreferredSymmetric) > 0 { + subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric}) + } + + if len(sig.PreferredHash) > 0 { + subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash}) + } + + if len(sig.PreferredCompression) > 0 { + subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression}) + } + + return +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/signature_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/signature_test.go new file mode 100644 index 00000000..c1bbde8b --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/signature_test.go @@ -0,0 +1,42 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "crypto" + "encoding/hex" + "testing" +) + +func TestSignatureRead(t *testing.T) { + packet, err := Read(readerFromHex(signatureDataHex)) + if err != nil { + t.Error(err) + return + } + sig, ok := packet.(*Signature) + if !ok || sig.SigType != SigTypeBinary || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.SHA1 { + t.Errorf("failed to parse, got: %#v", packet) + } +} + +func TestSignatureReserialize(t *testing.T) { + packet, _ := Read(readerFromHex(signatureDataHex)) + sig := packet.(*Signature) + out := new(bytes.Buffer) + err := sig.Serialize(out) + if err != nil { + t.Errorf("error reserializing: %s", err) + return + } + + expected, _ := hex.DecodeString(signatureDataHex) + if !bytes.Equal(expected, out.Bytes()) { + t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected)) + } +} + +const signatureDataHex = "c2c05c04000102000605024cb45112000a0910ab105c91af38fb158f8d07ff5596ea368c5efe015bed6e78348c0f033c931d5f2ce5db54ce7f2a7e4b4ad64db758d65a7a71773edeab7ba2a9e0908e6a94a1175edd86c1d843279f045b021a6971a72702fcbd650efc393c5474d5b59a15f96d2eaad4c4c426797e0dcca2803ef41c6ff234d403eec38f31d610c344c06f2401c262f0993b2e66cad8a81ebc4322c723e0d4ba09fe917e8777658307ad8329adacba821420741009dfe87f007759f0982275d028a392c6ed983a0d846f890b36148c7358bdb8a516007fac760261ecd06076813831a36d0459075d1befa245ae7f7fb103d92ca759e9498fe60ef8078a39a3beda510deea251ea9f0a7f0df6ef42060f20780360686f3e400e" diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/signature_v3.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/signature_v3.go new file mode 100644 index 00000000..7ad3b2b2 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/signature_v3.go @@ -0,0 +1,146 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "crypto" + "encoding/binary" + "fmt" + "io" + "strconv" + "time" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/s2k" +) + +// SignatureV3 represents older version 3 signatures. These signatures are less secure +// than version 4 and should not be used to create new signatures. They are included +// here for backwards compatibility to read and validate with older key material. +// See RFC 4880, section 5.2.2. +type SignatureV3 struct { + SigType SignatureType + CreationTime time.Time + IssuerKeyId uint64 + PubKeyAlgo PublicKeyAlgorithm + Hash crypto.Hash + HashTag [2]byte + + RSASignature parsedMPI + DSASigR, DSASigS parsedMPI +} + +func (sig *SignatureV3) parse(r io.Reader) (err error) { + // RFC 4880, section 5.2.2 + var buf [8]byte + if _, err = readFull(r, buf[:1]); err != nil { + return + } + if buf[0] < 2 || buf[0] > 3 { + err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) + return + } + if _, err = readFull(r, buf[:1]); err != nil { + return + } + if buf[0] != 5 { + err = errors.UnsupportedError( + "invalid hashed material length " + strconv.Itoa(int(buf[0]))) + return + } + + // Read hashed material: signature type + creation time + if _, err = readFull(r, buf[:5]); err != nil { + return + } + sig.SigType = SignatureType(buf[0]) + t := binary.BigEndian.Uint32(buf[1:5]) + sig.CreationTime = time.Unix(int64(t), 0) + + // Eight-octet Key ID of signer. + if _, err = readFull(r, buf[:8]); err != nil { + return + } + sig.IssuerKeyId = binary.BigEndian.Uint64(buf[:]) + + // Public-key and hash algorithm + if _, err = readFull(r, buf[:2]); err != nil { + return + } + sig.PubKeyAlgo = PublicKeyAlgorithm(buf[0]) + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA: + default: + err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) + return + } + var ok bool + if sig.Hash, ok = s2k.HashIdToHash(buf[1]); !ok { + return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) + } + + // Two-octet field holding left 16 bits of signed hash value. + if _, err = readFull(r, sig.HashTag[:2]); err != nil { + return + } + + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) + case PubKeyAlgoDSA: + if sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r); err != nil { + return + } + sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) + default: + panic("unreachable") + } + return +} + +// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been +// called first. +func (sig *SignatureV3) Serialize(w io.Writer) (err error) { + buf := make([]byte, 8) + + // Write the sig type and creation time + buf[0] = byte(sig.SigType) + binary.BigEndian.PutUint32(buf[1:5], uint32(sig.CreationTime.Unix())) + if _, err = w.Write(buf[:5]); err != nil { + return + } + + // Write the issuer long key ID + binary.BigEndian.PutUint64(buf[:8], sig.IssuerKeyId) + if _, err = w.Write(buf[:8]); err != nil { + return + } + + // Write public key algorithm, hash ID, and hash value + buf[0] = byte(sig.PubKeyAlgo) + hashId, ok := s2k.HashToHashId(sig.Hash) + if !ok { + return errors.UnsupportedError(fmt.Sprintf("hash function %v", sig.Hash)) + } + buf[1] = hashId + copy(buf[2:4], sig.HashTag[:]) + if _, err = w.Write(buf[:4]); err != nil { + return + } + + if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil { + return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") + } + + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + err = writeMPIs(w, sig.RSASignature) + case PubKeyAlgoDSA: + err = writeMPIs(w, sig.DSASigR, sig.DSASigS) + default: + panic("impossible") + } + return +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/signature_v3_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/signature_v3_test.go new file mode 100644 index 00000000..642d8a1b --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/signature_v3_test.go @@ -0,0 +1,92 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "crypto" + "encoding/hex" + "io" + "io/ioutil" + "testing" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/armor" +) + +func TestSignatureV3Read(t *testing.T) { + r := v3KeyReader(t) + Read(r) // Skip public key + Read(r) // Skip uid + packet, err := Read(r) // Signature + if err != nil { + t.Error(err) + return + } + sig, ok := packet.(*SignatureV3) + if !ok || sig.SigType != SigTypeGenericCert || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.MD5 { + t.Errorf("failed to parse, got: %#v", packet) + } +} + +func TestSignatureV3Reserialize(t *testing.T) { + r := v3KeyReader(t) + Read(r) // Skip public key + Read(r) // Skip uid + packet, err := Read(r) + if err != nil { + t.Error(err) + return + } + sig := packet.(*SignatureV3) + out := new(bytes.Buffer) + if err = sig.Serialize(out); err != nil { + t.Errorf("error reserializing: %s", err) + return + } + expected, err := ioutil.ReadAll(v3KeyReader(t)) + if err != nil { + t.Error(err) + return + } + expected = expected[4+141+4+39:] // See pgpdump offsets below, this is where the sig starts + if !bytes.Equal(expected, out.Bytes()) { + t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected)) + } +} + +func v3KeyReader(t *testing.T) io.Reader { + armorBlock, err := armor.Decode(bytes.NewBufferString(keySigV3Armor)) + if err != nil { + t.Fatalf("armor Decode failed: %v", err) + } + return armorBlock.Body +} + +// keySigV3Armor is some V3 public key I found in an SKS dump. +// Old: Public Key Packet(tag 6)(141 bytes) +// Ver 4 - new +// Public key creation time - Fri Sep 16 17:13:54 CDT 1994 +// Pub alg - unknown(pub 0) +// Unknown public key(pub 0) +// Old: User ID Packet(tag 13)(39 bytes) +// User ID - Armin M. Warda +// Old: Signature Packet(tag 2)(149 bytes) +// Ver 4 - new +// Sig type - unknown(05) +// Pub alg - ElGamal Encrypt-Only(pub 16) +// Hash alg - unknown(hash 46) +// Hashed Sub: unknown(sub 81, critical)(1988 bytes) +const keySigV3Armor = `-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: SKS 1.0.10 + +mI0CLnoYogAAAQQA1qwA2SuJwfQ5bCQ6u5t20ulnOtY0gykf7YjiK4LiVeRBwHjGq7v30tGV +5Qti7qqRW4Ww7CDCJc4sZMFnystucR2vLkXaSoNWoFm4Fg47NiisDdhDezHwbVPW6OpCFNSi +ZAamtj4QAUBu8j4LswafrJqZqR9336/V3g8Yil2l48kABRG0J0FybWluIE0uIFdhcmRhIDx3 +YXJkYUBuZXBoaWxpbS5ydWhyLmRlPoiVAgUQLok2xwXR6zmeWEiZAQE/DgP/WgxPQh40/Po4 +gSkWZCDAjNdph7zexvAb0CcUWahcwiBIgg3U5ErCx9I5CNVA9U+s8bNrDZwgSIeBzp3KhWUx +524uhGgm6ZUTOAIKA6CbV6pfqoLpJnRYvXYQU5mIWsNa99wcu2qu18OeEDnztb7aLA6Ra9OF +YFCbq4EjXRoOrYM= +=LPjs +-----END PGP PUBLIC KEY BLOCK-----` diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go new file mode 100644 index 00000000..7e3e7b78 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go @@ -0,0 +1,164 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "crypto/cipher" + "io" + "strconv" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/s2k" +) + +// This is the largest session key that we'll support. Since no 512-bit cipher +// has even been seriously used, this is comfortably large. +const maxSessionKeySizeInBytes = 64 + +// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC +// 4880, section 5.3. +type SymmetricKeyEncrypted struct { + CipherFunc CipherFunction + Encrypted bool + Key []byte // Empty unless Encrypted is false. + s2k func(out, in []byte) + encryptedKey []byte +} + +const symmetricKeyEncryptedVersion = 4 + +func (ske *SymmetricKeyEncrypted) parse(r io.Reader) (err error) { + // RFC 4880, section 5.3. + var buf [2]byte + _, err = readFull(r, buf[:]) + if err != nil { + return + } + if buf[0] != symmetricKeyEncryptedVersion { + return errors.UnsupportedError("SymmetricKeyEncrypted version") + } + ske.CipherFunc = CipherFunction(buf[1]) + + if ske.CipherFunc.KeySize() == 0 { + return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1]))) + } + + ske.s2k, err = s2k.Parse(r) + if err != nil { + return + } + + encryptedKey := make([]byte, maxSessionKeySizeInBytes) + // The session key may follow. We just have to try and read to find + // out. If it exists then we limit it to maxSessionKeySizeInBytes. + n, err := readFull(r, encryptedKey) + if err != nil && err != io.ErrUnexpectedEOF { + return + } + err = nil + if n != 0 { + if n == maxSessionKeySizeInBytes { + return errors.UnsupportedError("oversized encrypted session key") + } + ske.encryptedKey = encryptedKey[:n] + } + + ske.Encrypted = true + + return +} + +// Decrypt attempts to decrypt an encrypted session key. If it returns nil, +// ske.Key will contain the session key. +func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) error { + if !ske.Encrypted { + return nil + } + + key := make([]byte, ske.CipherFunc.KeySize()) + ske.s2k(key, passphrase) + + if len(ske.encryptedKey) == 0 { + ske.Key = key + } else { + // the IV is all zeros + iv := make([]byte, ske.CipherFunc.blockSize()) + c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv) + c.XORKeyStream(ske.encryptedKey, ske.encryptedKey) + ske.CipherFunc = CipherFunction(ske.encryptedKey[0]) + if ske.CipherFunc.blockSize() == 0 { + return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(ske.CipherFunc))) + } + ske.CipherFunc = CipherFunction(ske.encryptedKey[0]) + ske.Key = ske.encryptedKey[1:] + if len(ske.Key)%ske.CipherFunc.blockSize() != 0 { + ske.Key = nil + return errors.StructuralError("length of decrypted key not a multiple of block size") + } + } + + ske.Encrypted = false + return nil +} + +// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The +// packet contains a random session key, encrypted by a key derived from the +// given passphrase. The session key is returned and must be passed to +// SerializeSymmetricallyEncrypted. +// If config is nil, sensible defaults will be used. +func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) { + cipherFunc := config.Cipher() + keySize := cipherFunc.KeySize() + if keySize == 0 { + return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc))) + } + + s2kBuf := new(bytes.Buffer) + keyEncryptingKey := make([]byte, keySize) + // s2k.Serialize salts and stretches the passphrase, and writes the + // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf. + err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, &s2k.Config{Hash: config.Hash(), S2KCount: config.PasswordHashIterations()}) + if err != nil { + return + } + s2kBytes := s2kBuf.Bytes() + + packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize + err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength) + if err != nil { + return + } + + var buf [2]byte + buf[0] = symmetricKeyEncryptedVersion + buf[1] = byte(cipherFunc) + _, err = w.Write(buf[:]) + if err != nil { + return + } + _, err = w.Write(s2kBytes) + if err != nil { + return + } + + sessionKey := make([]byte, keySize) + _, err = io.ReadFull(config.Random(), sessionKey) + if err != nil { + return + } + iv := make([]byte, cipherFunc.blockSize()) + c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv) + encryptedCipherAndKey := make([]byte, keySize+1) + c.XORKeyStream(encryptedCipherAndKey, buf[1:]) + c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey) + _, err = w.Write(encryptedCipherAndKey) + if err != nil { + return + } + + key = sessionKey + return +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go new file mode 100644 index 00000000..dd983cb3 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go @@ -0,0 +1,102 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "encoding/hex" + "io" + "io/ioutil" + "testing" +) + +func TestSymmetricKeyEncrypted(t *testing.T) { + buf := readerFromHex(symmetricallyEncryptedHex) + packet, err := Read(buf) + if err != nil { + t.Errorf("failed to read SymmetricKeyEncrypted: %s", err) + return + } + ske, ok := packet.(*SymmetricKeyEncrypted) + if !ok { + t.Error("didn't find SymmetricKeyEncrypted packet") + return + } + err = ske.Decrypt([]byte("password")) + if err != nil { + t.Error(err) + return + } + + packet, err = Read(buf) + if err != nil { + t.Errorf("failed to read SymmetricallyEncrypted: %s", err) + return + } + se, ok := packet.(*SymmetricallyEncrypted) + if !ok { + t.Error("didn't find SymmetricallyEncrypted packet") + return + } + r, err := se.Decrypt(ske.CipherFunc, ske.Key) + if err != nil { + t.Error(err) + return + } + + contents, err := ioutil.ReadAll(r) + if err != nil && err != io.EOF { + t.Error(err) + return + } + + expectedContents, _ := hex.DecodeString(symmetricallyEncryptedContentsHex) + if !bytes.Equal(expectedContents, contents) { + t.Errorf("bad contents got:%x want:%x", contents, expectedContents) + } +} + +const symmetricallyEncryptedHex = "8c0d04030302371a0b38d884f02060c91cf97c9973b8e58e028e9501708ccfe618fb92afef7fa2d80ddadd93cf" +const symmetricallyEncryptedContentsHex = "cb1062004d14c4df636f6e74656e74732e0a" + +func TestSerializeSymmetricKeyEncrypted(t *testing.T) { + buf := bytes.NewBuffer(nil) + passphrase := []byte("testing") + config := &Config{ + DefaultCipher: CipherAES128, + } + + key, err := SerializeSymmetricKeyEncrypted(buf, passphrase, config) + if err != nil { + t.Errorf("failed to serialize: %s", err) + return + } + + p, err := Read(buf) + if err != nil { + t.Errorf("failed to reparse: %s", err) + return + } + ske, ok := p.(*SymmetricKeyEncrypted) + if !ok { + t.Errorf("parsed a different packet type: %#v", p) + return + } + + if !ske.Encrypted { + t.Errorf("SKE not encrypted but should be") + } + if ske.CipherFunc != config.DefaultCipher { + t.Errorf("SKE cipher function is %d (expected %d)", ske.CipherFunc, config.DefaultCipher) + } + err = ske.Decrypt(passphrase) + if err != nil { + t.Errorf("failed to decrypt reparsed SKE: %s", err) + return + } + if !bytes.Equal(key, ske.Key) { + t.Errorf("keys don't match after Decrpyt: %x (original) vs %x (parsed)", key, ske.Key) + } +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go new file mode 100644 index 00000000..87ab8def --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go @@ -0,0 +1,290 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "crypto/cipher" + "crypto/sha1" + "crypto/subtle" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "hash" + "io" + "strconv" +) + +// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The +// encrypted contents will consist of more OpenPGP packets. See RFC 4880, +// sections 5.7 and 5.13. +type SymmetricallyEncrypted struct { + MDC bool // true iff this is a type 18 packet and thus has an embedded MAC. + contents io.Reader + prefix []byte +} + +const symmetricallyEncryptedVersion = 1 + +func (se *SymmetricallyEncrypted) parse(r io.Reader) error { + if se.MDC { + // See RFC 4880, section 5.13. + var buf [1]byte + _, err := readFull(r, buf[:]) + if err != nil { + return err + } + if buf[0] != symmetricallyEncryptedVersion { + return errors.UnsupportedError("unknown SymmetricallyEncrypted version") + } + } + se.contents = r + return nil +} + +// Decrypt returns a ReadCloser, from which the decrypted contents of the +// packet can be read. An incorrect key can, with high probability, be detected +// immediately and this will result in a KeyIncorrect error being returned. +func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) { + keySize := c.KeySize() + if keySize == 0 { + return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c))) + } + if len(key) != keySize { + return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length") + } + + if se.prefix == nil { + se.prefix = make([]byte, c.blockSize()+2) + _, err := readFull(se.contents, se.prefix) + if err != nil { + return nil, err + } + } else if len(se.prefix) != c.blockSize()+2 { + return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths") + } + + ocfbResync := OCFBResync + if se.MDC { + // MDC packets use a different form of OCFB mode. + ocfbResync = OCFBNoResync + } + + s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync) + if s == nil { + return nil, errors.ErrKeyIncorrect + } + + plaintext := cipher.StreamReader{S: s, R: se.contents} + + if se.MDC { + // MDC packets have an embedded hash that we need to check. + h := sha1.New() + h.Write(se.prefix) + return &seMDCReader{in: plaintext, h: h}, nil + } + + // Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser. + return seReader{plaintext}, nil +} + +// seReader wraps an io.Reader with a no-op Close method. +type seReader struct { + in io.Reader +} + +func (ser seReader) Read(buf []byte) (int, error) { + return ser.in.Read(buf) +} + +func (ser seReader) Close() error { + return nil +} + +const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size + +// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold +// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an +// MDC packet containing a hash of the previous contents which is checked +// against the running hash. See RFC 4880, section 5.13. +type seMDCReader struct { + in io.Reader + h hash.Hash + trailer [mdcTrailerSize]byte + scratch [mdcTrailerSize]byte + trailerUsed int + error bool + eof bool +} + +func (ser *seMDCReader) Read(buf []byte) (n int, err error) { + if ser.error { + err = io.ErrUnexpectedEOF + return + } + if ser.eof { + err = io.EOF + return + } + + // If we haven't yet filled the trailer buffer then we must do that + // first. + for ser.trailerUsed < mdcTrailerSize { + n, err = ser.in.Read(ser.trailer[ser.trailerUsed:]) + ser.trailerUsed += n + if err == io.EOF { + if ser.trailerUsed != mdcTrailerSize { + n = 0 + err = io.ErrUnexpectedEOF + ser.error = true + return + } + ser.eof = true + n = 0 + return + } + + if err != nil { + n = 0 + return + } + } + + // If it's a short read then we read into a temporary buffer and shift + // the data into the caller's buffer. + if len(buf) <= mdcTrailerSize { + n, err = readFull(ser.in, ser.scratch[:len(buf)]) + copy(buf, ser.trailer[:n]) + ser.h.Write(buf[:n]) + copy(ser.trailer[:], ser.trailer[n:]) + copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:]) + if n < len(buf) { + ser.eof = true + err = io.EOF + } + return + } + + n, err = ser.in.Read(buf[mdcTrailerSize:]) + copy(buf, ser.trailer[:]) + ser.h.Write(buf[:n]) + copy(ser.trailer[:], buf[n:]) + + if err == io.EOF { + ser.eof = true + } + return +} + +// This is a new-format packet tag byte for a type 19 (MDC) packet. +const mdcPacketTagByte = byte(0x80) | 0x40 | 19 + +func (ser *seMDCReader) Close() error { + if ser.error { + return errors.SignatureError("error during reading") + } + + for !ser.eof { + // We haven't seen EOF so we need to read to the end + var buf [1024]byte + _, err := ser.Read(buf[:]) + if err == io.EOF { + break + } + if err != nil { + return errors.SignatureError("error during reading") + } + } + + if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size { + return errors.SignatureError("MDC packet not found") + } + ser.h.Write(ser.trailer[:2]) + + final := ser.h.Sum(nil) + if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 { + return errors.SignatureError("hash mismatch") + } + return nil +} + +// An seMDCWriter writes through to an io.WriteCloser while maintains a running +// hash of the data written. On close, it emits an MDC packet containing the +// running hash. +type seMDCWriter struct { + w io.WriteCloser + h hash.Hash +} + +func (w *seMDCWriter) Write(buf []byte) (n int, err error) { + w.h.Write(buf) + return w.w.Write(buf) +} + +func (w *seMDCWriter) Close() (err error) { + var buf [mdcTrailerSize]byte + + buf[0] = mdcPacketTagByte + buf[1] = sha1.Size + w.h.Write(buf[:2]) + digest := w.h.Sum(nil) + copy(buf[2:], digest) + + _, err = w.w.Write(buf[:]) + if err != nil { + return + } + return w.w.Close() +} + +// noOpCloser is like an ioutil.NopCloser, but for an io.Writer. +type noOpCloser struct { + w io.Writer +} + +func (c noOpCloser) Write(data []byte) (n int, err error) { + return c.w.Write(data) +} + +func (c noOpCloser) Close() error { + return nil +} + +// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet +// to w and returns a WriteCloser to which the to-be-encrypted packets can be +// written. +// If config is nil, sensible defaults will be used. +func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (contents io.WriteCloser, err error) { + if c.KeySize() != len(key) { + return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length") + } + writeCloser := noOpCloser{w} + ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC) + if err != nil { + return + } + + _, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion}) + if err != nil { + return + } + + block := c.new(key) + blockSize := block.BlockSize() + iv := make([]byte, blockSize) + _, err = config.Random().Read(iv) + if err != nil { + return + } + s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync) + _, err = ciphertext.Write(prefix) + if err != nil { + return + } + plaintext := cipher.StreamWriter{S: s, W: ciphertext} + + h := sha1.New() + h.Write(iv) + h.Write(iv[blockSize-2:]) + contents = &seMDCWriter{w: plaintext, h: h} + return +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go new file mode 100644 index 00000000..28b1bded --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go @@ -0,0 +1,123 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "crypto/sha1" + "encoding/hex" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "io" + "io/ioutil" + "testing" +) + +// TestReader wraps a []byte and returns reads of a specific length. +type testReader struct { + data []byte + stride int +} + +func (t *testReader) Read(buf []byte) (n int, err error) { + n = t.stride + if n > len(t.data) { + n = len(t.data) + } + if n > len(buf) { + n = len(buf) + } + copy(buf, t.data) + t.data = t.data[n:] + if len(t.data) == 0 { + err = io.EOF + } + return +} + +func testMDCReader(t *testing.T) { + mdcPlaintext, _ := hex.DecodeString(mdcPlaintextHex) + + for stride := 1; stride < len(mdcPlaintext)/2; stride++ { + r := &testReader{data: mdcPlaintext, stride: stride} + mdcReader := &seMDCReader{in: r, h: sha1.New()} + body, err := ioutil.ReadAll(mdcReader) + if err != nil { + t.Errorf("stride: %d, error: %s", stride, err) + continue + } + if !bytes.Equal(body, mdcPlaintext[:len(mdcPlaintext)-22]) { + t.Errorf("stride: %d: bad contents %x", stride, body) + continue + } + + err = mdcReader.Close() + if err != nil { + t.Errorf("stride: %d, error on Close: %s", stride, err) + } + } + + mdcPlaintext[15] ^= 80 + + r := &testReader{data: mdcPlaintext, stride: 2} + mdcReader := &seMDCReader{in: r, h: sha1.New()} + _, err := ioutil.ReadAll(mdcReader) + if err != nil { + t.Errorf("corruption test, error: %s", err) + return + } + err = mdcReader.Close() + if err == nil { + t.Error("corruption: no error") + } else if _, ok := err.(*errors.SignatureError); !ok { + t.Errorf("corruption: expected SignatureError, got: %s", err) + } +} + +const mdcPlaintextHex = "a302789c3b2d93c4e0eb9aba22283539b3203335af44a134afb800c849cb4c4de10200aff40b45d31432c80cb384299a0655966d6939dfdeed1dddf980" + +func TestSerialize(t *testing.T) { + buf := bytes.NewBuffer(nil) + c := CipherAES128 + key := make([]byte, c.KeySize()) + + w, err := SerializeSymmetricallyEncrypted(buf, c, key, nil) + if err != nil { + t.Errorf("error from SerializeSymmetricallyEncrypted: %s", err) + return + } + + contents := []byte("hello world\n") + + w.Write(contents) + w.Close() + + p, err := Read(buf) + if err != nil { + t.Errorf("error from Read: %s", err) + return + } + + se, ok := p.(*SymmetricallyEncrypted) + if !ok { + t.Errorf("didn't read a *SymmetricallyEncrypted") + return + } + + r, err := se.Decrypt(c, key) + if err != nil { + t.Errorf("error from Decrypt: %s", err) + return + } + + contentsCopy := bytes.NewBuffer(nil) + _, err = io.Copy(contentsCopy, r) + if err != nil { + t.Errorf("error from io.Copy: %s", err) + return + } + if !bytes.Equal(contentsCopy.Bytes(), contents) { + t.Errorf("contents not equal got: %x want: %x", contentsCopy.Bytes(), contents) + } +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/userattribute.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/userattribute.go new file mode 100644 index 00000000..96a2b382 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/userattribute.go @@ -0,0 +1,91 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "image" + "image/jpeg" + "io" + "io/ioutil" +) + +const UserAttrImageSubpacket = 1 + +// UserAttribute is capable of storing other types of data about a user +// beyond name, email and a text comment. In practice, user attributes are typically used +// to store a signed thumbnail photo JPEG image of the user. +// See RFC 4880, section 5.12. +type UserAttribute struct { + Contents []*OpaqueSubpacket +} + +// NewUserAttributePhoto creates a user attribute packet +// containing the given images. +func NewUserAttributePhoto(photos ...image.Image) (uat *UserAttribute, err error) { + uat = new(UserAttribute) + for _, photo := range photos { + var buf bytes.Buffer + // RFC 4880, Section 5.12.1. + data := []byte{ + 0x10, 0x00, // Little-endian image header length (16 bytes) + 0x01, // Image header version 1 + 0x01, // JPEG + 0, 0, 0, 0, // 12 reserved octets, must be all zero. + 0, 0, 0, 0, + 0, 0, 0, 0} + if _, err = buf.Write(data); err != nil { + return + } + if err = jpeg.Encode(&buf, photo, nil); err != nil { + return + } + uat.Contents = append(uat.Contents, &OpaqueSubpacket{ + SubType: UserAttrImageSubpacket, + Contents: buf.Bytes()}) + } + return +} + +// NewUserAttribute creates a new user attribute packet containing the given subpackets. +func NewUserAttribute(contents ...*OpaqueSubpacket) *UserAttribute { + return &UserAttribute{Contents: contents} +} + +func (uat *UserAttribute) parse(r io.Reader) (err error) { + // RFC 4880, section 5.13 + b, err := ioutil.ReadAll(r) + if err != nil { + return + } + uat.Contents, err = OpaqueSubpackets(b) + return +} + +// Serialize marshals the user attribute to w in the form of an OpenPGP packet, including +// header. +func (uat *UserAttribute) Serialize(w io.Writer) (err error) { + var buf bytes.Buffer + for _, sp := range uat.Contents { + sp.Serialize(&buf) + } + if err = serializeHeader(w, packetTypeUserAttribute, buf.Len()); err != nil { + return err + } + _, err = w.Write(buf.Bytes()) + return +} + +// ImageData returns zero or more byte slices, each containing +// JPEG File Interchange Format (JFIF), for each photo in the +// the user attribute packet. +func (uat *UserAttribute) ImageData() (imageData [][]byte) { + for _, sp := range uat.Contents { + if sp.SubType == UserAttrImageSubpacket && len(sp.Contents) > 16 { + imageData = append(imageData, sp.Contents[16:]) + } + } + return +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/userattribute_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/userattribute_test.go new file mode 100644 index 00000000..13ca5143 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/userattribute_test.go @@ -0,0 +1,109 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "encoding/base64" + "image/color" + "image/jpeg" + "testing" +) + +func TestParseUserAttribute(t *testing.T) { + r := base64.NewDecoder(base64.StdEncoding, bytes.NewBufferString(userAttributePacket)) + for i := 0; i < 2; i++ { + p, err := Read(r) + if err != nil { + t.Fatal(err) + } + uat := p.(*UserAttribute) + imgs := uat.ImageData() + if len(imgs) != 1 { + t.Errorf("Unexpected number of images in user attribute packet: %d", len(imgs)) + } + if len(imgs[0]) != 3395 { + t.Errorf("Unexpected JPEG image size: %d", len(imgs[0])) + } + img, err := jpeg.Decode(bytes.NewBuffer(imgs[0])) + if err != nil { + t.Errorf("Error decoding JPEG image: %v", err) + } + // A pixel in my right eye. + pixel := color.NRGBAModel.Convert(img.At(56, 36)) + ref := color.NRGBA{R: 157, G: 128, B: 124, A: 255} + if pixel != ref { + t.Errorf("Unexpected pixel color: %v", pixel) + } + w := bytes.NewBuffer(nil) + err = uat.Serialize(w) + if err != nil { + t.Errorf("Error writing user attribute: %v", err) + } + r = bytes.NewBuffer(w.Bytes()) + } +} + +const userAttributePacket = ` +0cyWzJQBEAABAQAAAAAAAAAAAAAAAP/Y/+AAEEpGSUYAAQIAAAEAAQAA/9sAQwAFAwQEBAMFBAQE +BQUFBgcMCAcHBwcPCgsJDBEPEhIRDxEQExYcFxMUGhUQERghGBocHR8fHxMXIiQiHiQcHh8e/9sA +QwEFBQUHBgcOCAgOHhQRFB4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e +Hh4eHh4eHh4e/8AAEQgAZABkAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYH +CAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHw +JDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6 +g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk +5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIB +AgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEX +GBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKT +lJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX2 +9/j5+v/aAAwDAQACEQMRAD8A5uGP06VehQ4pIox04q5EnHSvAep+hIIl4zVuMHGPWmRrUWtalaaN +pU2oXsgSGJSxPr6ClvoitErs0Itqjc7BQOpPAFYmrfEnwjojtHNqaXEynBjtx5hH4jj9a8B8d+Od +W8UXZjWR4LJT+7t0Jwfc+prnIdO1CWZEW2mZ3HyDactXXDB3V5s8evm1namj6r0H4weCLtxG+ova +ueP30RA/MV6not1bX0Ed1ZzxzwyDKvGwZSPqK+Ff+ES8R8t/ZV2oHUmM10Hgbxp4m8BatEfNnWBH +/eWshOxx9Kmpg4te49RUM1kn+8Wh9zQ4P1FaMC7l465rjPh14y0fxnoseoaXOpfaPOgJ+eI98j09 +67W19M15bi4uzPSqTU480WXkjZkAyAR61DPE6OCSOalWRRgZxjvTb598sfU4FBwx5uY4T4feIm8P +TeJbAgc65NIM+8cX+FFeLfF3Vr3SfiNrMFrMypJMJcDPUqP8KK+kpVFyLU+ar037SXqX4hxVpMY7 +1UhPpVlT2rybKx9smWYz3NeH/EDVLzxt40j8O6bITaQybPlbKkjq39K9O8fasdH8IahfKxWQRFIy +Ou9uB/OuE/Z/0y3j1d9TuyoZCMs5xjuea1pLli5nn46q240l13PcfhN8EvDNtpcEl/CklyVBLuMk +mvU/Dfwo0BL/AO13FjEDD/qyV7Vn+CvGPg8zRpJrVm8ikLtEg6+1ew2dxZ3EQaJgysuQPasH7eXW +1zzsbVhT92kk/PsYieEND+zlPs6c/wCyAPyryH4wfCPRtW0u6j+xRLOxLxSoADkDpXY+MPjJ4c0S +9k082d3O8ZKkxw5XI96ytK+IGk+IpFjRpod+Qq3C7QT6A1E6NenaXbqRg6rlLlqS0fRnxjpd1r/w +w8afa7GWRPKbZLGeBKmeVNfZngLxNaeKfDdprVjxHcLlkJ5Vh1H5185/tDad9h8XOsqAw3Cb0cjq +CfX61P8AsveKf7L8T3fhe5nxa3g324YniQdh9R/KuivTdSmp9TXB1/Z1nRlsfU249QBx1pWfcwI7 +Cq6u2Ovamb9rYz16V5x7Psz5q/aJhZfibcupIElvE3H+7j+lFbXx9szP45jlUfeso8/99OKK9elL +3EeNVopzZVharCtxVRGGMk02S5JyFOB69zWTieypnL/GksfB+0cr9oQt69awPhPpD69Y3Ky3DWth +CWluGU4LAdq3vibGs/g68BJygVxjrwRW5+ztoRv/AAs8EeCZnO/J/hzz/Kumi4wp3kePjlOdZKPY +ml8Mvo6WM9ppi7J0EkQYMzkb1X0wW+bJHGACa+ivg14huZPCkjXUO6SImIYOQAP6UQ2sGneHmiWF +CYoSAAuM8etXfhBpMr+EZ3SSNRcMx6ZxWdes6ytBGSwkMNFuo7pnP614Ut9Zn1C4uLySKcwObGFA +Qnm4+XcR71h+CfDHiKCQWuv2YWFtw+bBZQD8rcE8n2Ney+GbGGQSM6I7xvtI681rXdp8hKRRp6t3 +FYPE1VDlsY1nQjWdl+J8w/tOeDZZ/AMd/EGefTHyxxyYjwfyODXg3waRh8UtEcFh+8Jb8FNfZPxh +Ak8J6nbPIsiyW7LnseK+Ofh99ptPHFnf2lu0y2twGcKuSEPB/Q1WHk50miq1o14TXU+xop+On61H +NMC6Nis1LgsAcUTSt1APFcXJZn0EqmhyvxA037friTYziBV6f7Tf40Vr3k4aXLx5OMZIzRXZB2ik +efJXbPHJJcnaD9aN2R1qoGO8/WkuLlIV+YjdjpXSonQ5lTxfiTwzqCnkeQxx9BWx+zPrQsrBFYja +zEfrXL6lfie3khcjY6lSPUGud+G3iA6FrY0uQ/KJsA9gCa0jSvFpnBi6tpKSPu++nsIfDFxeXciR +qIicscY4rxTwB8RUkn1axsPEf2LTYx85kTGzqCUP8VcJ47+JOs+I0Hhq1njjt/ufIeSvq1VtE+Gs +eoaUbSHUrkHdu3WtuX5Ix81XRh7OL5jirVpV5Whdn0F8C/iX4auVn0i612T7bASoe8wjTAd89K9g +vtSt5NMa4t5lkRhgOh3Dn6V8aaz8KZrIR3OlQ6r56LySmSxxz06Vo/CHx34h0rxBP4XvJ5AjK2RP +nEbAEj6ZxjPrWM6fMmoswqJxqJ1VZnqHxn1NLPwveqWHmNC2BnnNcD8DfDkGi+CH1m+ijN1qMzNA +4GSIiAMf+hVxPxU8Tapc3c0F9MGCn5GU5BX0Pau3+HmrT3XgXSIJCBHDGdgAx1NYSpezha52Yauq +1dya2Wh2onAIwTj1p0lxxWWLkhRyCKWa5O3ORXOos9KVQluZm83j0oqi84JyWH50Vdmc7ep43d3I +t1Z2Iz2FYdxeSTsxyRnvTdVuDNcNluM9KrKcg817NOnZGNbEXdkNckjrXGeIIprPxFFdRHAlIwem +COtdmxrG8Q2cd/ZNExw45RvQ1bVjim+dWNzw7eaTD4mN3dndCQCo6hmI5zXpj/Ea/wBHjkh0kwRW +xXEfl4yTxXzXZalJDL9nuWKMmRnHcV2Hh3WreCyYXW2SWQhd5P3F6n+lS43d2cTm6d7Ox9EWPxH1 +ODQxPqWpCaSU/ukUc4z3/WvKW8UhviAdaMewYZG98gj9c1ymoa8LyWOJHwkTDaVPb0qpr+q2m6Nb +cfvNo349az9mou9iZVXNWbub3jm98/Vza2ReV7lsJg/e3dsV654UR9N0K0sZP9ZDGFbHr3rzL4P+ +H7rXfEEWr3I3W1qf3IYdW9fwqDxf4k8UeH/G95p08kscHmk25dPlZT0we9YTj7SXKjpw1aNG8mj3 +FLv5ccU959ycnmvKPDnxB82YQarGsZPAlTp+IrvIr1ZIgySKwIyCOhFYTpyg9T0qWIhVV4svzPvf +IdhgY4orPachj81FRdmtzxqdiZmJ9aQEgdqZcPtmbJ71DJcAZ5r20kkeXJtsfPIQDwPzrG1a+S3i +LyHAHvmp7y7HOD1rlNdm+1T7Acovf3o+J2RMpezjzMvrob67pX9o2ShZlYgg/wAWKxZLLWLZ/Ke3 +mVh14yK9M+BMC3dre2ko3LHKCB7EV7EngeGQJdQ7HyBkMKS0djgq1W3c+XtK03U522RwzsTwNiEk +ntXoHgf4calql9El/G8UZbLfLyfr7V9FeGvh+s+0Lbxxcglu2K1NW1nwN4Gk/wBLuI57tV5jjwzE +/QVNS+0dWYRqNvXRFv4eeCodKsY1ggVIY1G3K4z714h+1Jqul3GpwaXYeXJLbzgyyrg4b+6D+HNb +vjz436zq9m+naHF/ZdkeGfOZXH17V4Vqt2b29K+ZuOc5bnce5zWdPBShL2lTfojSeJhy+zp/NjVz +1Bwa6DSfFGq6fbJFDKrov8DjPFcu97ZxsUe4jVhwVJ5Bpp1mwQiLewJPXacVq6fNpYyjOUXdHoKf +EG8VQHsInbuVcgflRXnt5fIs2FYHgcgUVi8LG+xusdW/mN7U2KgEVkTzPt60UVfQ9eHxGHrV1MGi +iD4V25x1qvdgLAMd6KK0pbHm4x++dp8FtUubLxJ5EIjMc+A4Za+qfD8pe1JZVOBmiinW3RyRPMfi +R8QPE638+k2l6LK0Hylbddhb6nOa80mlkcmWR2kcnlnOSaKK7qCXKcNdu5narcSrAoBxvODWJIga +VckjDdqKKwq/EaQ0gUdbjQ6mr7QGBUcd6tPBC6gtGpOOuKKKie5qn7qIpEXd0HSiiimSf//Z` diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/userid.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/userid.go new file mode 100644 index 00000000..d6bea7d4 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/userid.go @@ -0,0 +1,160 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "io" + "io/ioutil" + "strings" +) + +// UserId contains text that is intended to represent the name and email +// address of the key holder. See RFC 4880, section 5.11. By convention, this +// takes the form "Full Name (Comment) " +type UserId struct { + Id string // By convention, this takes the form "Full Name (Comment) " which is split out in the fields below. + + Name, Comment, Email string +} + +func hasInvalidCharacters(s string) bool { + for _, c := range s { + switch c { + case '(', ')', '<', '>', 0: + return true + } + } + return false +} + +// NewUserId returns a UserId or nil if any of the arguments contain invalid +// characters. The invalid characters are '\x00', '(', ')', '<' and '>' +func NewUserId(name, comment, email string) *UserId { + // RFC 4880 doesn't deal with the structure of userid strings; the + // name, comment and email form is just a convention. However, there's + // no convention about escaping the metacharacters and GPG just refuses + // to create user ids where, say, the name contains a '('. We mirror + // this behaviour. + + if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) { + return nil + } + + uid := new(UserId) + uid.Name, uid.Comment, uid.Email = name, comment, email + uid.Id = name + if len(comment) > 0 { + if len(uid.Id) > 0 { + uid.Id += " " + } + uid.Id += "(" + uid.Id += comment + uid.Id += ")" + } + if len(email) > 0 { + if len(uid.Id) > 0 { + uid.Id += " " + } + uid.Id += "<" + uid.Id += email + uid.Id += ">" + } + return uid +} + +func (uid *UserId) parse(r io.Reader) (err error) { + // RFC 4880, section 5.11 + b, err := ioutil.ReadAll(r) + if err != nil { + return + } + uid.Id = string(b) + uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id) + return +} + +// Serialize marshals uid to w in the form of an OpenPGP packet, including +// header. +func (uid *UserId) Serialize(w io.Writer) error { + err := serializeHeader(w, packetTypeUserId, len(uid.Id)) + if err != nil { + return err + } + _, err = w.Write([]byte(uid.Id)) + return err +} + +// parseUserId extracts the name, comment and email from a user id string that +// is formatted as "Full Name (Comment) ". +func parseUserId(id string) (name, comment, email string) { + var n, c, e struct { + start, end int + } + var state int + + for offset, rune := range id { + switch state { + case 0: + // Entering name + n.start = offset + state = 1 + fallthrough + case 1: + // In name + if rune == '(' { + state = 2 + n.end = offset + } else if rune == '<' { + state = 5 + n.end = offset + } + case 2: + // Entering comment + c.start = offset + state = 3 + fallthrough + case 3: + // In comment + if rune == ')' { + state = 4 + c.end = offset + } + case 4: + // Between comment and email + if rune == '<' { + state = 5 + } + case 5: + // Entering email + e.start = offset + state = 6 + fallthrough + case 6: + // In email + if rune == '>' { + state = 7 + e.end = offset + } + default: + // After email + } + } + switch state { + case 1: + // ended in the name + n.end = len(id) + case 3: + // ended in comment + c.end = len(id) + case 6: + // ended in email + e.end = len(id) + } + + name = strings.TrimSpace(id[n.start:n.end]) + comment = strings.TrimSpace(id[c.start:c.end]) + email = strings.TrimSpace(id[e.start:e.end]) + return +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/userid_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/userid_test.go new file mode 100644 index 00000000..29681938 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet/userid_test.go @@ -0,0 +1,87 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "testing" +) + +var userIdTests = []struct { + id string + name, comment, email string +}{ + {"", "", "", ""}, + {"John Smith", "John Smith", "", ""}, + {"John Smith ()", "John Smith", "", ""}, + {"John Smith () <>", "John Smith", "", ""}, + {"(comment", "", "comment", ""}, + {"(comment)", "", "comment", ""}, + {" sdfk", "", "", "email"}, + {" John Smith ( Comment ) asdkflj < email > lksdfj", "John Smith", "Comment", "email"}, + {" John Smith < email > lksdfj", "John Smith", "", "email"}, + {"("}, + {"foo", "bar", "", "foo (bar)"}, + {"foo", "", "baz", "foo "}, + {"", "bar", "baz", "(bar) "}, + {"foo", "bar", "baz", "foo (bar) "}, +} + +func TestNewUserId(t *testing.T) { + for i, test := range newUserIdTests { + uid := NewUserId(test.name, test.comment, test.email) + if uid == nil { + t.Errorf("#%d: returned nil", i) + continue + } + if uid.Id != test.id { + t.Errorf("#%d: got '%s', want '%s'", i, uid.Id, test.id) + } + } +} + +var invalidNewUserIdTests = []struct { + name, comment, email string +}{ + {"foo(", "", ""}, + {"foo<", "", ""}, + {"", "bar)", ""}, + {"", "bar<", ""}, + {"", "", "baz>"}, + {"", "", "baz)"}, + {"", "", "baz\x00"}, +} + +func TestNewUserIdWithInvalidInput(t *testing.T) { + for i, test := range invalidNewUserIdTests { + if uid := NewUserId(test.name, test.comment, test.email); uid != nil { + t.Errorf("#%d: returned non-nil value: %#v", i, uid) + } + } +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/read.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/read.go new file mode 100644 index 00000000..6706ec59 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/read.go @@ -0,0 +1,427 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package openpgp implements high level operations on OpenPGP messages. +package openpgp + +import ( + "crypto" + _ "crypto/sha256" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/armor" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet" + "hash" + "io" + "strconv" +) + +// SignatureType is the armor type for a PGP signature. +var SignatureType = "PGP SIGNATURE" + +// readArmored reads an armored block with the given type. +func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) { + block, err := armor.Decode(r) + if err != nil { + return + } + + if block.Type != expectedType { + return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type) + } + + return block.Body, nil +} + +// MessageDetails contains the result of parsing an OpenPGP encrypted and/or +// signed message. +type MessageDetails struct { + IsEncrypted bool // true if the message was encrypted. + EncryptedToKeyIds []uint64 // the list of recipient key ids. + IsSymmetricallyEncrypted bool // true if a passphrase could have decrypted the message. + DecryptedWith Key // the private key used to decrypt the message, if any. + IsSigned bool // true if the message is signed. + SignedByKeyId uint64 // the key id of the signer, if any. + SignedBy *Key // the key of the signer, if available. + LiteralData *packet.LiteralData // the metadata of the contents + UnverifiedBody io.Reader // the contents of the message. + + // If IsSigned is true and SignedBy is non-zero then the signature will + // be verified as UnverifiedBody is read. The signature cannot be + // checked until the whole of UnverifiedBody is read so UnverifiedBody + // must be consumed until EOF before the data can trusted. Even if a + // message isn't signed (or the signer is unknown) the data may contain + // an authentication code that is only checked once UnverifiedBody has + // been consumed. Once EOF has been seen, the following fields are + // valid. (An authentication code failure is reported as a + // SignatureError error when reading from UnverifiedBody.) + SignatureError error // nil if the signature is good. + Signature *packet.Signature // the signature packet itself. + + decrypted io.ReadCloser +} + +// A PromptFunction is used as a callback by functions that may need to decrypt +// a private key, or prompt for a passphrase. It is called with a list of +// acceptable, encrypted private keys and a boolean that indicates whether a +// passphrase is usable. It should either decrypt a private key or return a +// passphrase to try. If the decrypted private key or given passphrase isn't +// correct, the function will be called again, forever. Any error returned will +// be passed up. +type PromptFunction func(keys []Key, symmetric bool) ([]byte, error) + +// A keyEnvelopePair is used to store a private key with the envelope that +// contains a symmetric key, encrypted with that key. +type keyEnvelopePair struct { + key Key + encryptedKey *packet.EncryptedKey +} + +// ReadMessage parses an OpenPGP message that may be signed and/or encrypted. +// The given KeyRing should contain both public keys (for signature +// verification) and, possibly encrypted, private keys for decrypting. +// If config is nil, sensible defaults will be used. +func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err error) { + var p packet.Packet + + var symKeys []*packet.SymmetricKeyEncrypted + var pubKeys []keyEnvelopePair + var se *packet.SymmetricallyEncrypted + + packets := packet.NewReader(r) + md = new(MessageDetails) + md.IsEncrypted = true + + // The message, if encrypted, starts with a number of packets + // containing an encrypted decryption key. The decryption key is either + // encrypted to a public key, or with a passphrase. This loop + // collects these packets. +ParsePackets: + for { + p, err = packets.Next() + if err != nil { + return nil, err + } + switch p := p.(type) { + case *packet.SymmetricKeyEncrypted: + // This packet contains the decryption key encrypted with a passphrase. + md.IsSymmetricallyEncrypted = true + symKeys = append(symKeys, p) + case *packet.EncryptedKey: + // This packet contains the decryption key encrypted to a public key. + md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId) + switch p.Algo { + case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal: + break + default: + continue + } + var keys []Key + if p.KeyId == 0 { + keys = keyring.DecryptionKeys() + } else { + keys = keyring.KeysById(p.KeyId) + } + for _, k := range keys { + pubKeys = append(pubKeys, keyEnvelopePair{k, p}) + } + case *packet.SymmetricallyEncrypted: + se = p + break ParsePackets + case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature: + // This message isn't encrypted. + if len(symKeys) != 0 || len(pubKeys) != 0 { + return nil, errors.StructuralError("key material not followed by encrypted message") + } + packets.Unread(p) + return readSignedMessage(packets, nil, keyring) + } + } + + var candidates []Key + var decrypted io.ReadCloser + + // Now that we have the list of encrypted keys we need to decrypt at + // least one of them or, if we cannot, we need to call the prompt + // function so that it can decrypt a key or give us a passphrase. +FindKey: + for { + // See if any of the keys already have a private key available + candidates = candidates[:0] + candidateFingerprints := make(map[string]bool) + + for _, pk := range pubKeys { + if pk.key.PrivateKey == nil { + continue + } + if !pk.key.PrivateKey.Encrypted { + if len(pk.encryptedKey.Key) == 0 { + pk.encryptedKey.Decrypt(pk.key.PrivateKey, config) + } + if len(pk.encryptedKey.Key) == 0 { + continue + } + decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key) + if err != nil && err != errors.ErrKeyIncorrect { + return nil, err + } + if decrypted != nil { + md.DecryptedWith = pk.key + break FindKey + } + } else { + fpr := string(pk.key.PublicKey.Fingerprint[:]) + if v := candidateFingerprints[fpr]; v { + continue + } + candidates = append(candidates, pk.key) + candidateFingerprints[fpr] = true + } + } + + if len(candidates) == 0 && len(symKeys) == 0 { + return nil, errors.ErrKeyIncorrect + } + + if prompt == nil { + return nil, errors.ErrKeyIncorrect + } + + passphrase, err := prompt(candidates, len(symKeys) != 0) + if err != nil { + return nil, err + } + + // Try the symmetric passphrase first + if len(symKeys) != 0 && passphrase != nil { + for _, s := range symKeys { + err = s.Decrypt(passphrase) + if err == nil && !s.Encrypted { + decrypted, err = se.Decrypt(s.CipherFunc, s.Key) + if err != nil && err != errors.ErrKeyIncorrect { + return nil, err + } + if decrypted != nil { + break FindKey + } + } + + } + } + } + + md.decrypted = decrypted + if err := packets.Push(decrypted); err != nil { + return nil, err + } + return readSignedMessage(packets, md, keyring) +} + +// readSignedMessage reads a possibly signed message if mdin is non-zero then +// that structure is updated and returned. Otherwise a fresh MessageDetails is +// used. +func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err error) { + if mdin == nil { + mdin = new(MessageDetails) + } + md = mdin + + var p packet.Packet + var h hash.Hash + var wrappedHash hash.Hash +FindLiteralData: + for { + p, err = packets.Next() + if err != nil { + return nil, err + } + switch p := p.(type) { + case *packet.Compressed: + if err := packets.Push(p.Body); err != nil { + return nil, err + } + case *packet.OnePassSignature: + if !p.IsLast { + return nil, errors.UnsupportedError("nested signatures") + } + + h, wrappedHash, err = hashForSignature(p.Hash, p.SigType) + if err != nil { + md = nil + return + } + + md.IsSigned = true + md.SignedByKeyId = p.KeyId + keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign) + if len(keys) > 0 { + md.SignedBy = &keys[0] + } + case *packet.LiteralData: + md.LiteralData = p + break FindLiteralData + } + } + + if md.SignedBy != nil { + md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md} + } else if md.decrypted != nil { + md.UnverifiedBody = checkReader{md} + } else { + md.UnverifiedBody = md.LiteralData.Body + } + + return md, nil +} + +// hashForSignature returns a pair of hashes that can be used to verify a +// signature. The signature may specify that the contents of the signed message +// should be preprocessed (i.e. to normalize line endings). Thus this function +// returns two hashes. The second should be used to hash the message itself and +// performs any needed preprocessing. +func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) { + if !hashId.Available() { + return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId))) + } + h := hashId.New() + + switch sigType { + case packet.SigTypeBinary: + return h, h, nil + case packet.SigTypeText: + return h, NewCanonicalTextHash(h), nil + } + + return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType))) +} + +// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF +// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger +// MDC checks. +type checkReader struct { + md *MessageDetails +} + +func (cr checkReader) Read(buf []byte) (n int, err error) { + n, err = cr.md.LiteralData.Body.Read(buf) + if err == io.EOF { + mdcErr := cr.md.decrypted.Close() + if mdcErr != nil { + err = mdcErr + } + } + return +} + +// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes +// the data as it is read. When it sees an EOF from the underlying io.Reader +// it parses and checks a trailing Signature packet and triggers any MDC checks. +type signatureCheckReader struct { + packets *packet.Reader + h, wrappedHash hash.Hash + md *MessageDetails +} + +func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) { + n, err = scr.md.LiteralData.Body.Read(buf) + scr.wrappedHash.Write(buf[:n]) + if err == io.EOF { + var p packet.Packet + p, scr.md.SignatureError = scr.packets.Next() + if scr.md.SignatureError != nil { + return + } + + var ok bool + if scr.md.Signature, ok = p.(*packet.Signature); !ok { + scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature") + return + } + + scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature) + + // The SymmetricallyEncrypted packet, if any, might have an + // unsigned hash of its own. In order to check this we need to + // close that Reader. + if scr.md.decrypted != nil { + mdcErr := scr.md.decrypted.Close() + if mdcErr != nil { + err = mdcErr + } + } + } + return +} + +// CheckDetachedSignature takes a signed file and a detached signature and +// returns the signer if the signature is valid. If the signer isn't known, +// ErrUnknownIssuer is returned. +func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { + p, err := packet.Read(signature) + if err != nil { + return + } + + var issuerKeyId uint64 + var hashFunc crypto.Hash + var sigType packet.SignatureType + + switch sig := p.(type) { + case *packet.Signature: + if sig.IssuerKeyId == nil { + return nil, errors.StructuralError("signature doesn't have an issuer") + } + issuerKeyId = *sig.IssuerKeyId + hashFunc = sig.Hash + sigType = sig.SigType + case *packet.SignatureV3: + issuerKeyId = sig.IssuerKeyId + hashFunc = sig.Hash + sigType = sig.SigType + default: + return nil, errors.StructuralError("non signature packet found") + } + + h, wrappedHash, err := hashForSignature(hashFunc, sigType) + if err != nil { + return + } + + _, err = io.Copy(wrappedHash, signed) + if err != nil && err != io.EOF { + return + } + + keys := keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign) + if len(keys) == 0 { + return nil, errors.ErrUnknownIssuer + } + + for _, key := range keys { + switch sig := p.(type) { + case *packet.Signature: + err = key.PublicKey.VerifySignature(h, sig) + case *packet.SignatureV3: + err = key.PublicKey.VerifySignatureV3(h, sig) + } + if err == nil { + return key.Entity, nil + } + } + + if err == nil { + err = errors.ErrUnknownIssuer + } + return nil, err +} + +// CheckArmoredDetachedSignature performs the same actions as +// CheckDetachedSignature but expects the signature to be armored. +func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { + body, err := readArmored(signature, SignatureType) + if err != nil { + return + } + + return CheckDetachedSignature(keyring, signed, body) +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/read_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/read_test.go new file mode 100644 index 00000000..299d88e2 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/read_test.go @@ -0,0 +1,463 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package openpgp + +import ( + "bytes" + _ "crypto/sha512" + "encoding/hex" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "io" + "io/ioutil" + "strings" + "testing" +) + +func readerFromHex(s string) io.Reader { + data, err := hex.DecodeString(s) + if err != nil { + panic("readerFromHex: bad input") + } + return bytes.NewBuffer(data) +} + +func TestReadKeyRing(t *testing.T) { + kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex)) + if err != nil { + t.Error(err) + return + } + if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B { + t.Errorf("bad keyring: %#v", kring) + } +} + +func TestRereadKeyRing(t *testing.T) { + kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex)) + if err != nil { + t.Errorf("error in initial parse: %s", err) + return + } + out := new(bytes.Buffer) + err = kring[0].Serialize(out) + if err != nil { + t.Errorf("error in serialization: %s", err) + return + } + kring, err = ReadKeyRing(out) + if err != nil { + t.Errorf("error in second parse: %s", err) + return + } + + if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB { + t.Errorf("bad keyring: %#v", kring) + } +} + +func TestReadPrivateKeyRing(t *testing.T) { + kring, err := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) + if err != nil { + t.Error(err) + return + } + if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B || kring[0].PrimaryKey == nil { + t.Errorf("bad keyring: %#v", kring) + } +} + +func TestReadDSAKey(t *testing.T) { + kring, err := ReadKeyRing(readerFromHex(dsaTestKeyHex)) + if err != nil { + t.Error(err) + return + } + if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0x0CCC0360 { + t.Errorf("bad parse: %#v", kring) + } +} + +func TestDSAHashTruncatation(t *testing.T) { + // dsaKeyWithSHA512 was generated with GnuPG and --cert-digest-algo + // SHA512 in order to require DSA hash truncation to verify correctly. + _, err := ReadKeyRing(readerFromHex(dsaKeyWithSHA512)) + if err != nil { + t.Error(err) + } +} + +func TestGetKeyById(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) + + keys := kring.KeysById(0xa34d7e18c20c31bb) + if len(keys) != 1 || keys[0].Entity != kring[0] { + t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys) + } + + keys = kring.KeysById(0xfd94408d4543314f) + if len(keys) != 1 || keys[0].Entity != kring[0] { + t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys) + } +} + +func checkSignedMessage(t *testing.T, signedHex, expected string) { + kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) + + md, err := ReadMessage(readerFromHex(signedHex), kring, nil, nil) + if err != nil { + t.Error(err) + return + } + + if !md.IsSigned || md.SignedByKeyId != 0xa34d7e18c20c31bb || md.SignedBy == nil || md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) != 0 || md.IsSymmetricallyEncrypted { + t.Errorf("bad MessageDetails: %#v", md) + } + + contents, err := ioutil.ReadAll(md.UnverifiedBody) + if err != nil { + t.Errorf("error reading UnverifiedBody: %s", err) + } + if string(contents) != expected { + t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected) + } + if md.SignatureError != nil || md.Signature == nil { + t.Errorf("failed to validate: %s", md.SignatureError) + } +} + +func TestSignedMessage(t *testing.T) { + checkSignedMessage(t, signedMessageHex, signedInput) +} + +func TestTextSignedMessage(t *testing.T) { + checkSignedMessage(t, signedTextMessageHex, signedTextInput) +} + +// The reader should detect "compressed quines", which are compressed +// packets that expand into themselves and cause an infinite recursive +// parsing loop. +// The packet in this test case comes from Taylor R. Campbell at +// http://mumble.net/~campbell/misc/pgp-quine/ +func TestCampbellQuine(t *testing.T) { + md, err := ReadMessage(readerFromHex(campbellQuine), nil, nil, nil) + if md != nil { + t.Errorf("Reading a compressed quine should not return any data: %#v", md) + } + structural, ok := err.(errors.StructuralError) + if !ok { + t.Fatalf("Unexpected class of error: %T", err) + } + if !strings.Contains(string(structural), "too many layers of packets") { + t.Fatalf("Unexpected error: %s", err) + } +} + +var signedEncryptedMessageTests = []struct { + keyRingHex string + messageHex string + signedByKeyId uint64 + encryptedToKeyId uint64 +}{ + { + testKeys1And2PrivateHex, + signedEncryptedMessageHex, + 0xa34d7e18c20c31bb, + 0x2a67d68660df41c7, + }, + { + dsaElGamalTestKeysHex, + signedEncryptedMessage2Hex, + 0x33af447ccd759b09, + 0xcf6a7abcd43e3673, + }, +} + +func TestSignedEncryptedMessage(t *testing.T) { + for i, test := range signedEncryptedMessageTests { + expected := "Signed and encrypted message\n" + kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex)) + prompt := func(keys []Key, symmetric bool) ([]byte, error) { + if symmetric { + t.Errorf("prompt: message was marked as symmetrically encrypted") + return nil, errors.ErrKeyIncorrect + } + + if len(keys) == 0 { + t.Error("prompt: no keys requested") + return nil, errors.ErrKeyIncorrect + } + + err := keys[0].PrivateKey.Decrypt([]byte("passphrase")) + if err != nil { + t.Errorf("prompt: error decrypting key: %s", err) + return nil, errors.ErrKeyIncorrect + } + + return nil, nil + } + + md, err := ReadMessage(readerFromHex(test.messageHex), kring, prompt, nil) + if err != nil { + t.Errorf("#%d: error reading message: %s", i, err) + return + } + + if !md.IsSigned || md.SignedByKeyId != test.signedByKeyId || md.SignedBy == nil || !md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) == 0 || md.EncryptedToKeyIds[0] != test.encryptedToKeyId { + t.Errorf("#%d: bad MessageDetails: %#v", i, md) + } + + contents, err := ioutil.ReadAll(md.UnverifiedBody) + if err != nil { + t.Errorf("#%d: error reading UnverifiedBody: %s", i, err) + } + if string(contents) != expected { + t.Errorf("#%d: bad UnverifiedBody got:%s want:%s", i, string(contents), expected) + } + + if md.SignatureError != nil || md.Signature == nil { + t.Errorf("#%d: failed to validate: %s", i, md.SignatureError) + } + } +} + +func TestUnspecifiedRecipient(t *testing.T) { + expected := "Recipient unspecified\n" + kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) + + md, err := ReadMessage(readerFromHex(recipientUnspecifiedHex), kring, nil, nil) + if err != nil { + t.Errorf("error reading message: %s", err) + return + } + + contents, err := ioutil.ReadAll(md.UnverifiedBody) + if err != nil { + t.Errorf("error reading UnverifiedBody: %s", err) + } + if string(contents) != expected { + t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected) + } +} + +func TestSymmetricallyEncrypted(t *testing.T) { + expected := "Symmetrically encrypted.\n" + + prompt := func(keys []Key, symmetric bool) ([]byte, error) { + if len(keys) != 0 { + t.Errorf("prompt: len(keys) = %d (want 0)", len(keys)) + } + + if !symmetric { + t.Errorf("symmetric is not set") + } + + return []byte("password"), nil + } + + md, err := ReadMessage(readerFromHex(symmetricallyEncryptedCompressedHex), nil, prompt, nil) + if err != nil { + t.Errorf("ReadMessage: %s", err) + return + } + + contents, err := ioutil.ReadAll(md.UnverifiedBody) + if err != nil { + t.Errorf("ReadAll: %s", err) + } + + expectedCreationTime := uint32(1295992998) + if md.LiteralData.Time != expectedCreationTime { + t.Errorf("LiteralData.Time is %d, want %d", md.LiteralData.Time, expectedCreationTime) + } + + if string(contents) != expected { + t.Errorf("contents got: %s want: %s", string(contents), expected) + } +} + +func testDetachedSignature(t *testing.T, kring KeyRing, signature io.Reader, sigInput, tag string, expectedSignerKeyId uint64) { + signed := bytes.NewBufferString(sigInput) + signer, err := CheckDetachedSignature(kring, signed, signature) + if err != nil { + t.Errorf("%s: signature error: %s", tag, err) + return + } + if signer == nil { + t.Errorf("%s: signer is nil", tag) + return + } + if signer.PrimaryKey.KeyId != expectedSignerKeyId { + t.Errorf("%s: wrong signer got:%x want:%x", tag, signer.PrimaryKey.KeyId, expectedSignerKeyId) + } +} + +func TestDetachedSignature(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) + testDetachedSignature(t, kring, readerFromHex(detachedSignatureHex), signedInput, "binary", testKey1KeyId) + testDetachedSignature(t, kring, readerFromHex(detachedSignatureTextHex), signedInput, "text", testKey1KeyId) + testDetachedSignature(t, kring, readerFromHex(detachedSignatureV3TextHex), signedInput, "v3", testKey1KeyId) + + incorrectSignedInput := signedInput + "X" + _, err := CheckDetachedSignature(kring, bytes.NewBufferString(incorrectSignedInput), readerFromHex(detachedSignatureHex)) + if err == nil { + t.Fatal("CheckDetachedSignature returned without error for bad signature") + } + if err == errors.ErrUnknownIssuer { + t.Fatal("CheckDetachedSignature returned ErrUnknownIssuer when the signer was known, but the signature invalid") + } +} + +func TestDetachedSignatureDSA(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyHex)) + testDetachedSignature(t, kring, readerFromHex(detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId) +} + +func testHashFunctionError(t *testing.T, signatureHex string) { + kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) + _, err := CheckDetachedSignature(kring, nil, readerFromHex(signatureHex)) + if err == nil { + t.Fatal("Packet with bad hash type was correctly parsed") + } + unsupported, ok := err.(errors.UnsupportedError) + if !ok { + t.Fatalf("Unexpected class of error: %s", err) + } + if !strings.Contains(string(unsupported), "hash ") { + t.Fatalf("Unexpected error: %s", err) + } +} + +func TestUnknownHashFunction(t *testing.T) { + // unknownHashFunctionHex contains a signature packet with hash + // function type 153 (which isn't a real hash function id). + testHashFunctionError(t, unknownHashFunctionHex) +} + +func TestMissingHashFunction(t *testing.T) { + // missingHashFunctionHex contains a signature packet that uses + // RIPEMD160, which isn't compiled in. + testHashFunctionError(t, missingHashFunctionHex) +} + +func TestReadingArmoredPrivateKey(t *testing.T) { + el, err := ReadArmoredKeyRing(bytes.NewBufferString(armoredPrivateKeyBlock)) + if err != nil { + t.Error(err) + } + if len(el) != 1 { + t.Errorf("got %d entities, wanted 1\n", len(el)) + } +} + +func TestReadingArmoredPublicKey(t *testing.T) { + el, err := ReadArmoredKeyRing(bytes.NewBufferString(e2ePublicKey)) + if err != nil { + t.Error(err) + } + if len(el) != 1 { + t.Errorf("didn't get a valid entity") + } +} + +func TestNoArmoredData(t *testing.T) { + _, err := ReadArmoredKeyRing(bytes.NewBufferString("foo")) + if _, ok := err.(errors.InvalidArgumentError); !ok { + t.Errorf("error was not an InvalidArgumentError: %s", err) + } +} + +const testKey1KeyId = 0xA34D7E18C20C31BB +const testKey3KeyId = 0x338934250CCC0360 + +const signedInput = "Signed message\nline 2\nline 3\n" +const signedTextInput = "Signed message\r\nline 2\r\nline 3\r\n" + +const recipientUnspecifiedHex = "848c0300000000000000000103ff62d4d578d03cf40c3da998dfe216c074fa6ddec5e31c197c9666ba292830d91d18716a80f699f9d897389a90e6d62d0238f5f07a5248073c0f24920e4bc4a30c2d17ee4e0cae7c3d4aaa4e8dced50e3010a80ee692175fa0385f62ecca4b56ee6e9980aa3ec51b61b077096ac9e800edaf161268593eedb6cc7027ff5cb32745d250010d407a6221ae22ef18469b444f2822478c4d190b24d36371a95cb40087cdd42d9399c3d06a53c0673349bfb607927f20d1e122bde1e2bf3aa6cae6edf489629bcaa0689539ae3b718914d88ededc3b" + +const detachedSignatureHex = "889c04000102000605024d449cd1000a0910a34d7e18c20c31bb167603ff57718d09f28a519fdc7b5a68b6a3336da04df85e38c5cd5d5bd2092fa4629848a33d85b1729402a2aab39c3ac19f9d573f773cc62c264dc924c067a79dfd8a863ae06c7c8686120760749f5fd9b1e03a64d20a7df3446ddc8f0aeadeaeba7cbaee5c1e366d65b6a0c6cc749bcb912d2f15013f812795c2e29eb7f7b77f39ce77" + +const detachedSignatureTextHex = "889c04010102000605024d449d21000a0910a34d7e18c20c31bbc8c60400a24fbef7342603a41cb1165767bd18985d015fb72fe05db42db36cfb2f1d455967f1e491194fbf6cf88146222b23bf6ffbd50d17598d976a0417d3192ff9cc0034fd00f287b02e90418bbefe609484b09231e4e7a5f3562e199bf39909ab5276c4d37382fe088f6b5c3426fc1052865da8b3ab158672d58b6264b10823dc4b39" + +const detachedSignatureV3TextHex = "8900950305005255c25ca34d7e18c20c31bb0102bb3f04009f6589ef8a028d6e54f6eaf25432e590d31c3a41f4710897585e10c31e5e332c7f9f409af8512adceaff24d0da1474ab07aa7bce4f674610b010fccc5b579ae5eb00a127f272fb799f988ab8e4574c141da6dbfecfef7e6b2c478d9a3d2551ba741f260ee22bec762812f0053e05380bfdd55ad0f22d8cdf71b233fe51ae8a24" + +const detachedSignatureDSAHex = "884604001102000605024d6c4eac000a0910338934250ccc0360f18d00a087d743d6405ed7b87755476629600b8b694a39e900a0abff8126f46faf1547c1743c37b21b4ea15b8f83" + +const testKeys1And2Hex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b0020003b88d044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f0011010001889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab0020003988d044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b0020003b88d044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020003" + +const testKeys1And2PrivateHex = "9501d8044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd00110100010003ff4d91393b9a8e3430b14d6209df42f98dc927425b881f1209f319220841273a802a97c7bdb8b3a7740b3ab5866c4d1d308ad0d3a79bd1e883aacf1ac92dfe720285d10d08752a7efe3c609b1d00f17f2805b217be53999a7da7e493bfc3e9618fd17018991b8128aea70a05dbce30e4fbe626aa45775fa255dd9177aabf4df7cf0200c1ded12566e4bc2bb590455e5becfb2e2c9796482270a943343a7835de41080582c2be3caf5981aa838140e97afa40ad652a0b544f83eb1833b0957dce26e47b0200eacd6046741e9ce2ec5beb6fb5e6335457844fb09477f83b050a96be7da043e17f3a9523567ed40e7a521f818813a8b8a72209f1442844843ccc7eb9805442570200bdafe0438d97ac36e773c7162028d65844c4d463e2420aa2228c6e50dc2743c3d6c72d0d782a5173fe7be2169c8a9f4ef8a7cf3e37165e8c61b89c346cdc6c1799d2b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b00200009d01d8044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f00110100010003fd17a7490c22a79c59281fb7b20f5e6553ec0c1637ae382e8adaea295f50241037f8997cf42c1ce26417e015091451b15424b2c59eb8d4161b0975630408e394d3b00f88d4b4e18e2cc85e8251d4753a27c639c83f5ad4a571c4f19d7cd460b9b73c25ade730c99df09637bd173d8e3e981ac64432078263bb6dc30d3e974150dd0200d0ee05be3d4604d2146fb0457f31ba17c057560785aa804e8ca5530a7cd81d3440d0f4ba6851efcfd3954b7e68908fc0ba47f7ac37bf559c6c168b70d3a7c8cd0200da1c677c4bce06a068070f2b3733b0a714e88d62aa3f9a26c6f5216d48d5c2b5624144f3807c0df30be66b3268eeeca4df1fbded58faf49fc95dc3c35f134f8b01fd1396b6c0fc1b6c4f0eb8f5e44b8eace1e6073e20d0b8bc5385f86f1cf3f050f66af789f3ef1fc107b7f4421e19e0349c730c68f0a226981f4e889054fdb4dc149e8e889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab00200009501fe044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001fe030302e9030f3c783e14856063f16938530e148bc57a7aa3f3e4f90df9dceccdc779bc0835e1ad3d006e4a8d7b36d08b8e0de5a0d947254ecfbd22037e6572b426bcfdc517796b224b0036ff90bc574b5509bede85512f2eefb520fb4b02aa523ba739bff424a6fe81c5041f253f8d757e69a503d3563a104d0d49e9e890b9d0c26f96b55b743883b472caa7050c4acfd4a21f875bdf1258d88bd61224d303dc9df77f743137d51e6d5246b88c406780528fd9a3e15bab5452e5b93970d9dcc79f48b38651b9f15bfbcf6da452837e9cc70683d1bdca94507870f743e4ad902005812488dd342f836e72869afd00ce1850eea4cfa53ce10e3608e13d3c149394ee3cbd0e23d018fcbcb6e2ec5a1a22972d1d462ca05355d0d290dd2751e550d5efb38c6c89686344df64852bf4ff86638708f644e8ec6bd4af9b50d8541cb91891a431326ab2e332faa7ae86cfb6e0540aa63160c1e5cdd5a4add518b303fff0a20117c6bc77f7cfbaf36b04c865c6c2b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b00200009d01fe044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001fe030302e9030f3c783e148560f936097339ae381d63116efcf802ff8b1c9360767db5219cc987375702a4123fd8657d3e22700f23f95020d1b261eda5257e9a72f9a918e8ef22dd5b3323ae03bbc1923dd224db988cadc16acc04b120a9f8b7e84da9716c53e0334d7b66586ddb9014df604b41be1e960dcfcbc96f4ed150a1a0dd070b9eb14276b9b6be413a769a75b519a53d3ecc0c220e85cd91ca354d57e7344517e64b43b6e29823cbd87eae26e2b2e78e6dedfbb76e3e9f77bcb844f9a8932eb3db2c3f9e44316e6f5d60e9e2a56e46b72abe6b06dc9a31cc63f10023d1f5e12d2a3ee93b675c96f504af0001220991c88db759e231b3320dcedf814dcf723fd9857e3d72d66a0f2af26950b915abdf56c1596f46a325bf17ad4810d3535fb02a259b247ac3dbd4cc3ecf9c51b6c07cebb009c1506fba0a89321ec8683e3fd009a6e551d50243e2d5092fefb3321083a4bad91320dc624bd6b5dddf93553e3d53924c05bfebec1fb4bd47e89a1a889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020000" + +const dsaElGamalTestKeysHex = "9501e1044dfcb16a110400aa3e5c1a1f43dd28c2ffae8abf5cfce555ee874134d8ba0a0f7b868ce2214beddc74e5e1e21ded354a95d18acdaf69e5e342371a71fbb9093162e0c5f3427de413a7f2c157d83f5cd2f9d791256dc4f6f0e13f13c3302af27f2384075ab3021dff7a050e14854bbde0a1094174855fc02f0bae8e00a340d94a1f22b32e48485700a0cec672ac21258fb95f61de2ce1af74b2c4fa3e6703ff698edc9be22c02ae4d916e4fa223f819d46582c0516235848a77b577ea49018dcd5e9e15cff9dbb4663a1ae6dd7580fa40946d40c05f72814b0f88481207e6c0832c3bded4853ebba0a7e3bd8e8c66df33d5a537cd4acf946d1080e7a3dcea679cb2b11a72a33a2b6a9dc85f466ad2ddf4c3db6283fa645343286971e3dd700703fc0c4e290d45767f370831a90187e74e9972aae5bff488eeff7d620af0362bfb95c1a6c3413ab5d15a2e4139e5d07a54d72583914661ed6a87cce810be28a0aa8879a2dd39e52fb6fe800f4f181ac7e328f740cde3d09a05cecf9483e4cca4253e60d4429ffd679d9996a520012aad119878c941e3cf151459873bdfc2a9563472fe0303027a728f9feb3b864260a1babe83925ce794710cfd642ee4ae0e5b9d74cee49e9c67b6cd0ea5dfbb582132195a121356a1513e1bca73e5b80c58c7ccb4164453412f456c47616d616c2054657374204b65792031886204131102002205024dfcb16a021b03060b090807030206150802090a0b0416020301021e01021780000a091033af447ccd759b09fadd00a0b8fd6f5a790bad7e9f2dbb7632046dc4493588db009c087c6a9ba9f7f49fab221587a74788c00db4889ab00200009d0157044dfcb16a1004008dec3f9291205255ccff8c532318133a6840739dd68b03ba942676f9038612071447bf07d00d559c5c0875724ea16a4c774f80d8338b55fca691a0522e530e604215b467bbc9ccfd483a1da99d7bc2648b4318fdbd27766fc8bfad3fddb37c62b8ae7ccfe9577e9b8d1e77c1d417ed2c2ef02d52f4da11600d85d3229607943700030503ff506c94c87c8cab778e963b76cf63770f0a79bf48fb49d3b4e52234620fc9f7657f9f8d56c96a2b7c7826ae6b57ebb2221a3fe154b03b6637cea7e6d98e3e45d87cf8dc432f723d3d71f89c5192ac8d7290684d2c25ce55846a80c9a7823f6acd9bb29fa6cd71f20bc90eccfca20451d0c976e460e672b000df49466408d527affe0303027a728f9feb3b864260abd761730327bca2aaa4ea0525c175e92bf240682a0e83b226f97ecb2e935b62c9a133858ce31b271fa8eb41f6a1b3cd72a63025ce1a75ee4180dcc284884904181102000905024dfcb16a021b0c000a091033af447ccd759b09dd0b009e3c3e7296092c81bee5a19929462caaf2fff3ae26009e218c437a2340e7ea628149af1ec98ec091a43992b00200009501e1044dfcb1be1104009f61faa61aa43df75d128cbe53de528c4aec49ce9360c992e70c77072ad5623de0a3a6212771b66b39a30dad6781799e92608316900518ec01184a85d872365b7d2ba4bacfb5882ea3c2473d3750dc6178cc1cf82147fb58caa28b28e9f12f6d1efcb0534abed644156c91cca4ab78834268495160b2400bc422beb37d237c2300a0cac94911b6d493bda1e1fbc6feeca7cb7421d34b03fe22cec6ccb39675bb7b94a335c2b7be888fd3906a1125f33301d8aa6ec6ee6878f46f73961c8d57a3e9544d8ef2a2cbfd4d52da665b1266928cfe4cb347a58c412815f3b2d2369dec04b41ac9a71cc9547426d5ab941cccf3b18575637ccfb42df1a802df3cfe0a999f9e7109331170e3a221991bf868543960f8c816c28097e503fe319db10fb98049f3a57d7c80c420da66d56f3644371631fad3f0ff4040a19a4fedc2d07727a1b27576f75a4d28c47d8246f27071e12d7a8de62aad216ddbae6aa02efd6b8a3e2818cda48526549791ab277e447b3a36c57cefe9b592f5eab73959743fcc8e83cbefec03a329b55018b53eec196765ae40ef9e20521a603c551efe0303020950d53a146bf9c66034d00c23130cce95576a2ff78016ca471276e8227fb30b1ffbd92e61804fb0c3eff9e30b1a826ee8f3e4730b4d86273ca977b4164453412f456c47616d616c2054657374204b65792032886204131102002205024dfcb1be021b03060b090807030206150802090a0b0416020301021e01021780000a0910a86bf526325b21b22bd9009e34511620415c974750a20df5cb56b182f3b48e6600a0a9466cb1a1305a84953445f77d461593f1d42bc1b00200009d0157044dfcb1be1004009565a951da1ee87119d600c077198f1c1bceb0f7aa54552489298e41ff788fa8f0d43a69871f0f6f77ebdfb14a4260cf9fbeb65d5844b4272a1904dd95136d06c3da745dc46327dd44a0f16f60135914368c8039a34033862261806bb2c5ce1152e2840254697872c85441ccb7321431d75a747a4bfb1d2c66362b51ce76311700030503fc0ea76601c196768070b7365a200e6ddb09307f262d5f39eec467b5f5784e22abdf1aa49226f59ab37cb49969d8f5230ea65caf56015abda62604544ed526c5c522bf92bed178a078789f6c807b6d34885688024a5bed9e9f8c58d11d4b82487b44c5f470c5606806a0443b79cadb45e0f897a561a53f724e5349b9267c75ca17fe0303020950d53a146bf9c660bc5f4ce8f072465e2d2466434320c1e712272fafc20e342fe7608101580fa1a1a367e60486a7cd1246b7ef5586cf5e10b32762b710a30144f12dd17dd4884904181102000905024dfcb1be021b0c000a0910a86bf526325b21b2904c00a0b2b66b4b39ccffda1d10f3ea8d58f827e30a8b8e009f4255b2d8112a184e40cde43a34e8655ca7809370b0020000" + +const signedMessageHex = "a3019bc0cbccc0c4b8d8b74ee2108fe16ec6d3ca490cbe362d3f8333d3f352531472538b8b13d353b97232f352158c20943157c71c16064626063656269052062e4e01987e9b6fccff4b7df3a34c534b23e679cbec3bc0f8f6e64dfb4b55fe3f8efa9ce110ddb5cd79faf1d753c51aecfa669f7e7aa043436596cccc3359cb7dd6bbe9ecaa69e5989d9e57209571edc0b2fa7f57b9b79a64ee6e99ce1371395fee92fec2796f7b15a77c386ff668ee27f6d38f0baa6c438b561657377bf6acff3c5947befd7bf4c196252f1d6e5c524d0300" + +const signedTextMessageHex = "a3019bc0cbccc8c4b8d8b74ee2108fe16ec6d36a250cbece0c178233d3f352531472538b8b13d35379b97232f352158ca0b4312f57c71c1646462606365626906a062e4e019811591798ff99bf8afee860b0d8a8c2a85c3387e3bcf0bb3b17987f2bbcfab2aa526d930cbfd3d98757184df3995c9f3e7790e36e3e9779f06089d4c64e9e47dd6202cb6e9bc73c5d11bb59fbaf89d22d8dc7cf199ddf17af96e77c5f65f9bbed56f427bd8db7af37f6c9984bf9385efaf5f184f986fb3e6adb0ecfe35bbf92d16a7aa2a344fb0bc52fb7624f0200" + +const signedEncryptedMessageHex = "848c032a67d68660df41c70103ff5789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8d2c03b018bd210b1d3791e1aba74b0f1034e122ab72e760492c192383cf5e20b5628bd043272d63df9b923f147eb6091cd897553204832aba48fec54aa447547bb16305a1024713b90e77fd0065f1918271947549205af3c74891af22ee0b56cd29bfec6d6e351901cd4ab3ece7c486f1e32a792d4e474aed98ee84b3f591c7dff37b64e0ecd68fd036d517e412dcadf85840ce184ad7921ad446c4ee28db80447aea1ca8d4f574db4d4e37688158ddd19e14ee2eab4873d46947d65d14a23e788d912cf9a19624ca7352469b72a83866b7c23cb5ace3deab3c7018061b0ba0f39ed2befe27163e5083cf9b8271e3e3d52cc7ad6e2a3bd81d4c3d7022f8d" + +const signedEncryptedMessage2Hex = "85010e03cf6a7abcd43e36731003fb057f5495b79db367e277cdbe4ab90d924ddee0c0381494112ff8c1238fb0184af35d1731573b01bc4c55ecacd2aafbe2003d36310487d1ecc9ac994f3fada7f9f7f5c3a64248ab7782906c82c6ff1303b69a84d9a9529c31ecafbcdb9ba87e05439897d87e8a2a3dec55e14df19bba7f7bd316291c002ae2efd24f83f9e3441203fc081c0c23dc3092a454ca8a082b27f631abf73aca341686982e8fbda7e0e7d863941d68f3de4a755c2964407f4b5e0477b3196b8c93d551dd23c8beef7d0f03fbb1b6066f78907faf4bf1677d8fcec72651124080e0b7feae6b476e72ab207d38d90b958759fdedfc3c6c35717c9dbfc979b3cfbbff0a76d24a5e57056bb88acbd2a901ef64bc6e4db02adc05b6250ff378de81dca18c1910ab257dff1b9771b85bb9bbe0a69f5989e6d1710a35e6dfcceb7d8fb5ccea8db3932b3d9ff3fe0d327597c68b3622aec8e3716c83a6c93f497543b459b58ba504ed6bcaa747d37d2ca746fe49ae0a6ce4a8b694234e941b5159ff8bd34b9023da2814076163b86f40eed7c9472f81b551452d5ab87004a373c0172ec87ea6ce42ccfa7dbdad66b745496c4873d8019e8c28d6b3" + +const symmetricallyEncryptedCompressedHex = "8c0d04030302eb4a03808145d0d260c92f714339e13de5a79881216431925bf67ee2898ea61815f07894cd0703c50d0a76ef64d482196f47a8bc729af9b80bb6" + +const dsaTestKeyHex = "9901a2044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794" + +const dsaTestKeyPrivateHex = "9501bb044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4d00009f592e0619d823953577d4503061706843317e4fee083db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794" + +const armoredPrivateKeyBlock = `-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: GnuPG v1.4.10 (GNU/Linux) + +lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp +idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn +vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB +AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X +0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL +IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk +VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn +gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9 +TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx +q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz +dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA +CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1 +ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+ +eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid +AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV +bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK +/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA +A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX +TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc +lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6 +rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN +oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8 +QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU +nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC +AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp +BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad +AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL +VrM0m72/jnpKo04= +=zNCn +-----END PGP PRIVATE KEY BLOCK-----` + +const e2ePublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- +Charset: UTF-8 + +xv8AAABSBAAAAAATCCqGSM49AwEHAgME1LRoXSpOxtHXDUdmuvzchyg6005qIBJ4 +sfaSxX7QgH9RV2ONUhC+WiayCNADq+UMzuR/vunSr4aQffXvuGnR383/AAAAFDxk +Z2lsQHlhaG9vLWluYy5jb20+wv8AAACGBBATCAA4/wAAAAWCVGvAG/8AAAACiwn/ +AAAACZC2VkQCOjdvYf8AAAAFlQgJCgv/AAAAA5YBAv8AAAACngEAAE1BAP0X8veD +24IjmI5/C6ZAfVNXxgZZFhTAACFX75jUA3oD6AEAzoSwKf1aqH6oq62qhCN/pekX ++WAsVMBhNwzLpqtCRjLO/wAAAFYEAAAAABIIKoZIzj0DAQcCAwT50ain7vXiIRv8 +B1DO3x3cE/aattZ5sHNixJzRCXi2vQIA5QmOxZ6b5jjUekNbdHG3SZi1a2Ak5mfX +fRxC/5VGAwEIB8L/AAAAZQQYEwgAGP8AAAAFglRrwBz/AAAACZC2VkQCOjdvYQAA +FJAA9isX3xtGyMLYwp2F3nXm7QEdY5bq5VUcD/RJlj792VwA/1wH0pCzVLl4Q9F9 +ex7En5r7rHR5xwX82Msc+Rq9dSyO +=7MrZ +-----END PGP PUBLIC KEY BLOCK-----` + +const dsaKeyWithSHA512 = `9901a2044f04b07f110400db244efecc7316553ee08d179972aab87bb1214de7692593fcf5b6feb1c80fba268722dd464748539b85b81d574cd2d7ad0ca2444de4d849b8756bad7768c486c83a824f9bba4af773d11742bdfb4ac3b89ef8cc9452d4aad31a37e4b630d33927bff68e879284a1672659b8b298222fc68f370f3e24dccacc4a862442b9438b00a0ea444a24088dc23e26df7daf8f43cba3bffc4fe703fe3d6cd7fdca199d54ed8ae501c30e3ec7871ea9cdd4cf63cfe6fc82281d70a5b8bb493f922cd99fba5f088935596af087c8d818d5ec4d0b9afa7f070b3d7c1dd32a84fca08d8280b4890c8da1dde334de8e3cad8450eed2a4a4fcc2db7b8e5528b869a74a7f0189e11ef097ef1253582348de072bb07a9fa8ab838e993cef0ee203ff49298723e2d1f549b00559f886cd417a41692ce58d0ac1307dc71d85a8af21b0cf6eaa14baf2922d3a70389bedf17cc514ba0febbd107675a372fe84b90162a9e88b14d4b1c6be855b96b33fb198c46f058568817780435b6936167ebb3724b680f32bf27382ada2e37a879b3d9de2abe0c3f399350afd1ad438883f4791e2e3b4184453412068617368207472756e636174696f6e207465737488620413110a002205024f04b07f021b03060b090807030206150802090a0b0416020301021e01021780000a0910ef20e0cefca131581318009e2bf3bf047a44d75a9bacd00161ee04d435522397009a03a60d51bd8a568c6c021c8d7cf1be8d990d6417b0020003` + +const unknownHashFunctionHex = `8a00000040040001990006050253863c24000a09103b4fe6acc0b21f32ffff01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101` + +const missingHashFunctionHex = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101` + +const campbellQuine = `a0b001000300fcffa0b001000d00f2ff000300fcffa0b001000d00f2ff8270a01c00000500faff8270a01c00000500faff000500faff001400ebff8270a01c00000500faff000500faff001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400000000ffff000000ffff000b00f4ff428821c400000000ffff000000ffff000b00f4ff0233214c40000100feff000233214c40000100feff0000` diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/s2k/s2k.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/s2k/s2k.go new file mode 100644 index 00000000..02ff658c --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/s2k/s2k.go @@ -0,0 +1,273 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package s2k implements the various OpenPGP string-to-key transforms as +// specified in RFC 4800 section 3.7.1. +package s2k + +import ( + "crypto" + "hash" + "io" + "strconv" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" +) + +// Config collects configuration parameters for s2k key-stretching +// transformatioms. A nil *Config is valid and results in all default +// values. Currently, Config is used only by the Serialize function in +// this package. +type Config struct { + // Hash is the default hash function to be used. If + // nil, SHA1 is used. + Hash crypto.Hash + // S2KCount is only used for symmetric encryption. It + // determines the strength of the passphrase stretching when + // the said passphrase is hashed to produce a key. S2KCount + // should be between 1024 and 65011712, inclusive. If Config + // is nil or S2KCount is 0, the value 65536 used. Not all + // values in the above range can be represented. S2KCount will + // be rounded up to the next representable value if it cannot + // be encoded exactly. When set, it is strongly encrouraged to + // use a value that is at least 65536. See RFC 4880 Section + // 3.7.1.3. + S2KCount int +} + +func (c *Config) hash() crypto.Hash { + if c == nil || uint(c.Hash) == 0 { + // SHA1 is the historical default in this package. + return crypto.SHA1 + } + + return c.Hash +} + +func (c *Config) encodedCount() uint8 { + if c == nil || c.S2KCount == 0 { + return 96 // The common case. Correspoding to 65536 + } + + i := c.S2KCount + switch { + // Behave like GPG. Should we make 65536 the lowest value used? + case i < 1024: + i = 1024 + case i > 65011712: + i = 65011712 + } + + return encodeCount(i) +} + +// encodeCount converts an iterative "count" in the range 1024 to +// 65011712, inclusive, to an encoded count. The return value is the +// octet that is actually stored in the GPG file. encodeCount panics +// if i is not in the above range (encodedCount above takes care to +// pass i in the correct range). See RFC 4880 Section 3.7.7.1. +func encodeCount(i int) uint8 { + if i < 1024 || i > 65011712 { + panic("count arg i outside the required range") + } + + for encoded := 0; encoded < 256; encoded++ { + count := decodeCount(uint8(encoded)) + if count >= i { + return uint8(encoded) + } + } + + return 255 +} + +// decodeCount returns the s2k mode 3 iterative "count" corresponding to +// the encoded octet c. +func decodeCount(c uint8) int { + return (16 + int(c&15)) << (uint32(c>>4) + 6) +} + +// Simple writes to out the result of computing the Simple S2K function (RFC +// 4880, section 3.7.1.1) using the given hash and input passphrase. +func Simple(out []byte, h hash.Hash, in []byte) { + Salted(out, h, in, nil) +} + +var zero [1]byte + +// Salted writes to out the result of computing the Salted S2K function (RFC +// 4880, section 3.7.1.2) using the given hash, input passphrase and salt. +func Salted(out []byte, h hash.Hash, in []byte, salt []byte) { + done := 0 + var digest []byte + + for i := 0; done < len(out); i++ { + h.Reset() + for j := 0; j < i; j++ { + h.Write(zero[:]) + } + h.Write(salt) + h.Write(in) + digest = h.Sum(digest[:0]) + n := copy(out[done:], digest) + done += n + } +} + +// Iterated writes to out the result of computing the Iterated and Salted S2K +// function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase, +// salt and iteration count. +func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) { + combined := make([]byte, len(in)+len(salt)) + copy(combined, salt) + copy(combined[len(salt):], in) + + if count < len(combined) { + count = len(combined) + } + + done := 0 + var digest []byte + for i := 0; done < len(out); i++ { + h.Reset() + for j := 0; j < i; j++ { + h.Write(zero[:]) + } + written := 0 + for written < count { + if written+len(combined) > count { + todo := count - written + h.Write(combined[:todo]) + written = count + } else { + h.Write(combined) + written += len(combined) + } + } + digest = h.Sum(digest[:0]) + n := copy(out[done:], digest) + done += n + } +} + +// Parse reads a binary specification for a string-to-key transformation from r +// and returns a function which performs that transform. +func Parse(r io.Reader) (f func(out, in []byte), err error) { + var buf [9]byte + + _, err = io.ReadFull(r, buf[:2]) + if err != nil { + return + } + + hash, ok := HashIdToHash(buf[1]) + if !ok { + return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1]))) + } + if !hash.Available() { + return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash))) + } + h := hash.New() + + switch buf[0] { + case 0: + f := func(out, in []byte) { + Simple(out, h, in) + } + return f, nil + case 1: + _, err = io.ReadFull(r, buf[:8]) + if err != nil { + return + } + f := func(out, in []byte) { + Salted(out, h, in, buf[:8]) + } + return f, nil + case 3: + _, err = io.ReadFull(r, buf[:9]) + if err != nil { + return + } + count := decodeCount(buf[8]) + f := func(out, in []byte) { + Iterated(out, h, in, buf[:8], count) + } + return f, nil + } + + return nil, errors.UnsupportedError("S2K function") +} + +// Serialize salts and stretches the given passphrase and writes the +// resulting key into key. It also serializes an S2K descriptor to +// w. The key stretching can be configured with c, which may be +// nil. In that case, sensible defaults will be used. +func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Config) error { + var buf [11]byte + buf[0] = 3 /* iterated and salted */ + buf[1], _ = HashToHashId(c.hash()) + salt := buf[2:10] + if _, err := io.ReadFull(rand, salt); err != nil { + return err + } + encodedCount := c.encodedCount() + count := decodeCount(encodedCount) + buf[10] = encodedCount + if _, err := w.Write(buf[:]); err != nil { + return err + } + + Iterated(key, c.hash().New(), passphrase, salt, count) + return nil +} + +// hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with +// Go's crypto.Hash type. See RFC 4880, section 9.4. +var hashToHashIdMapping = []struct { + id byte + hash crypto.Hash + name string +}{ + {1, crypto.MD5, "MD5"}, + {2, crypto.SHA1, "SHA1"}, + {3, crypto.RIPEMD160, "RIPEMD160"}, + {8, crypto.SHA256, "SHA256"}, + {9, crypto.SHA384, "SHA384"}, + {10, crypto.SHA512, "SHA512"}, + {11, crypto.SHA224, "SHA224"}, +} + +// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP +// hash id. +func HashIdToHash(id byte) (h crypto.Hash, ok bool) { + for _, m := range hashToHashIdMapping { + if m.id == id { + return m.hash, true + } + } + return 0, false +} + +// HashIdToString returns the name of the hash function corresponding to the +// given OpenPGP hash id, or panics if id is unknown. +func HashIdToString(id byte) (name string, ok bool) { + for _, m := range hashToHashIdMapping { + if m.id == id { + return m.name, true + } + } + + return "", false +} + +// HashIdToHash returns an OpenPGP hash id which corresponds the given Hash. +func HashToHashId(h crypto.Hash) (id byte, ok bool) { + for _, m := range hashToHashIdMapping { + if m.hash == h { + return m.id, true + } + } + return 0, false +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/s2k/s2k_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/s2k/s2k_test.go new file mode 100644 index 00000000..183d2605 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/s2k/s2k_test.go @@ -0,0 +1,137 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package s2k + +import ( + "bytes" + "crypto" + _ "crypto/md5" + "crypto/rand" + "crypto/sha1" + _ "crypto/sha256" + _ "crypto/sha512" + "encoding/hex" + "testing" + + _ "golang.org/x/crypto/ripemd160" +) + +var saltedTests = []struct { + in, out string +}{ + {"hello", "10295ac1"}, + {"world", "ac587a5e"}, + {"foo", "4dda8077"}, + {"bar", "bd8aac6b9ea9cae04eae6a91c6133b58b5d9a61c14f355516ed9370456"}, + {"x", "f1d3f289"}, + {"xxxxxxxxxxxxxxxxxxxxxxx", "e00d7b45"}, +} + +func TestSalted(t *testing.T) { + h := sha1.New() + salt := [4]byte{1, 2, 3, 4} + + for i, test := range saltedTests { + expected, _ := hex.DecodeString(test.out) + out := make([]byte, len(expected)) + Salted(out, h, []byte(test.in), salt[:]) + if !bytes.Equal(expected, out) { + t.Errorf("#%d, got: %x want: %x", i, out, expected) + } + } +} + +var iteratedTests = []struct { + in, out string +}{ + {"hello", "83126105"}, + {"world", "6fa317f9"}, + {"foo", "8fbc35b9"}, + {"bar", "2af5a99b54f093789fd657f19bd245af7604d0f6ae06f66602a46a08ae"}, + {"x", "5a684dfe"}, + {"xxxxxxxxxxxxxxxxxxxxxxx", "18955174"}, +} + +func TestIterated(t *testing.T) { + h := sha1.New() + salt := [4]byte{4, 3, 2, 1} + + for i, test := range iteratedTests { + expected, _ := hex.DecodeString(test.out) + out := make([]byte, len(expected)) + Iterated(out, h, []byte(test.in), salt[:], 31) + if !bytes.Equal(expected, out) { + t.Errorf("#%d, got: %x want: %x", i, out, expected) + } + } +} + +var parseTests = []struct { + spec, in, out string +}{ + /* Simple with SHA1 */ + {"0002", "hello", "aaf4c61d"}, + /* Salted with SHA1 */ + {"01020102030405060708", "hello", "f4f7d67e"}, + /* Iterated with SHA1 */ + {"03020102030405060708f1", "hello", "f2a57b7c"}, +} + +func TestParse(t *testing.T) { + for i, test := range parseTests { + spec, _ := hex.DecodeString(test.spec) + buf := bytes.NewBuffer(spec) + f, err := Parse(buf) + if err != nil { + t.Errorf("%d: Parse returned error: %s", i, err) + continue + } + + expected, _ := hex.DecodeString(test.out) + out := make([]byte, len(expected)) + f(out, []byte(test.in)) + if !bytes.Equal(out, expected) { + t.Errorf("%d: output got: %x want: %x", i, out, expected) + } + if testing.Short() { + break + } + } +} + +func TestSerialize(t *testing.T) { + hashes := []crypto.Hash{crypto.MD5, crypto.SHA1, crypto.RIPEMD160, + crypto.SHA256, crypto.SHA384, crypto.SHA512, crypto.SHA224} + testCounts := []int{-1, 0, 1024, 65536, 4063232, 65011712} + for _, h := range hashes { + for _, c := range testCounts { + testSerializeConfig(t, &Config{Hash: h, S2KCount: c}) + } + } +} + +func testSerializeConfig(t *testing.T, c *Config) { + t.Logf("Running testSerializeConfig() with config: %+v", c) + + buf := bytes.NewBuffer(nil) + key := make([]byte, 16) + passphrase := []byte("testing") + err := Serialize(buf, key, rand.Reader, passphrase, c) + if err != nil { + t.Errorf("failed to serialize: %s", err) + return + } + + f, err := Parse(buf) + if err != nil { + t.Errorf("failed to reparse: %s", err) + return + } + key2 := make([]byte, len(key)) + f(key2, passphrase) + if !bytes.Equal(key2, key) { + t.Errorf("keys don't match: %x (serialied) vs %x (parsed)", key, key2) + } +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/write.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/write.go new file mode 100644 index 00000000..0e41e1c7 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/write.go @@ -0,0 +1,374 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package openpgp + +import ( + "crypto" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/armor" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/errors" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/packet" + "github.com/khlieng/name_pending/Godeps/_workspace/src/golang.org/x/crypto/openpgp/s2k" + "hash" + "io" + "strconv" + "time" +) + +// DetachSign signs message with the private key from signer (which must +// already have been decrypted) and writes the signature to w. +// If config is nil, sensible defaults will be used. +func DetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { + return detachSign(w, signer, message, packet.SigTypeBinary, config) +} + +// ArmoredDetachSign signs message with the private key from signer (which +// must already have been decrypted) and writes an armored signature to w. +// If config is nil, sensible defaults will be used. +func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) (err error) { + return armoredDetachSign(w, signer, message, packet.SigTypeBinary, config) +} + +// DetachSignText signs message (after canonicalising the line endings) with +// the private key from signer (which must already have been decrypted) and +// writes the signature to w. +// If config is nil, sensible defaults will be used. +func DetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { + return detachSign(w, signer, message, packet.SigTypeText, config) +} + +// ArmoredDetachSignText signs message (after canonicalising the line endings) +// with the private key from signer (which must already have been decrypted) +// and writes an armored signature to w. +// If config is nil, sensible defaults will be used. +func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { + return armoredDetachSign(w, signer, message, packet.SigTypeText, config) +} + +func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { + out, err := armor.Encode(w, SignatureType, nil) + if err != nil { + return + } + err = detachSign(out, signer, message, sigType, config) + if err != nil { + return + } + return out.Close() +} + +func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { + if signer.PrivateKey == nil { + return errors.InvalidArgumentError("signing key doesn't have a private key") + } + if signer.PrivateKey.Encrypted { + return errors.InvalidArgumentError("signing key is encrypted") + } + + sig := new(packet.Signature) + sig.SigType = sigType + sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo + sig.Hash = config.Hash() + sig.CreationTime = config.Now() + sig.IssuerKeyId = &signer.PrivateKey.KeyId + + h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType) + if err != nil { + return + } + io.Copy(wrappedHash, message) + + err = sig.Sign(h, signer.PrivateKey, config) + if err != nil { + return + } + + return sig.Serialize(w) +} + +// FileHints contains metadata about encrypted files. This metadata is, itself, +// encrypted. +type FileHints struct { + // IsBinary can be set to hint that the contents are binary data. + IsBinary bool + // FileName hints at the name of the file that should be written. It's + // truncated to 255 bytes if longer. It may be empty to suggest that the + // file should not be written to disk. It may be equal to "_CONSOLE" to + // suggest the data should not be written to disk. + FileName string + // ModTime contains the modification time of the file, or the zero time if not applicable. + ModTime time.Time +} + +// SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase. +// The resulting WriteCloser must be closed after the contents of the file have +// been written. +// If config is nil, sensible defaults will be used. +func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { + if hints == nil { + hints = &FileHints{} + } + + key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, passphrase, config) + if err != nil { + return + } + w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config) + if err != nil { + return + } + + literaldata := w + if algo := config.Compression(); algo != packet.CompressionNone { + var compConfig *packet.CompressionConfig + if config != nil { + compConfig = config.CompressionConfig + } + literaldata, err = packet.SerializeCompressed(w, algo, compConfig) + if err != nil { + return + } + } + + var epochSeconds uint32 + if !hints.ModTime.IsZero() { + epochSeconds = uint32(hints.ModTime.Unix()) + } + return packet.SerializeLiteral(literaldata, hints.IsBinary, hints.FileName, epochSeconds) +} + +// intersectPreferences mutates and returns a prefix of a that contains only +// the values in the intersection of a and b. The order of a is preserved. +func intersectPreferences(a []uint8, b []uint8) (intersection []uint8) { + var j int + for _, v := range a { + for _, v2 := range b { + if v == v2 { + a[j] = v + j++ + break + } + } + } + + return a[:j] +} + +func hashToHashId(h crypto.Hash) uint8 { + v, ok := s2k.HashToHashId(h) + if !ok { + panic("tried to convert unknown hash") + } + return v +} + +// Encrypt encrypts a message to a number of recipients and, optionally, signs +// it. hints contains optional information, that is also encrypted, that aids +// the recipients in processing the message. The resulting WriteCloser must +// be closed after the contents of the file have been written. +// If config is nil, sensible defaults will be used. +func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { + var signer *packet.PrivateKey + if signed != nil { + signKey, ok := signed.signingKey(config.Now()) + if !ok { + return nil, errors.InvalidArgumentError("no valid signing keys") + } + signer = signKey.PrivateKey + if signer.Encrypted { + return nil, errors.InvalidArgumentError("signing key must be decrypted") + } + } + + // These are the possible ciphers that we'll use for the message. + candidateCiphers := []uint8{ + uint8(packet.CipherAES128), + uint8(packet.CipherAES256), + uint8(packet.CipherCAST5), + } + // These are the possible hash functions that we'll use for the signature. + candidateHashes := []uint8{ + hashToHashId(crypto.SHA256), + hashToHashId(crypto.SHA512), + hashToHashId(crypto.SHA1), + hashToHashId(crypto.RIPEMD160), + } + // In the event that a recipient doesn't specify any supported ciphers + // or hash functions, these are the ones that we assume that every + // implementation supports. + defaultCiphers := candidateCiphers[len(candidateCiphers)-1:] + defaultHashes := candidateHashes[len(candidateHashes)-1:] + + encryptKeys := make([]Key, len(to)) + for i := range to { + var ok bool + encryptKeys[i], ok = to[i].encryptionKey(config.Now()) + if !ok { + return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys") + } + + sig := to[i].primaryIdentity().SelfSignature + + preferredSymmetric := sig.PreferredSymmetric + if len(preferredSymmetric) == 0 { + preferredSymmetric = defaultCiphers + } + preferredHashes := sig.PreferredHash + if len(preferredHashes) == 0 { + preferredHashes = defaultHashes + } + candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric) + candidateHashes = intersectPreferences(candidateHashes, preferredHashes) + } + + if len(candidateCiphers) == 0 || len(candidateHashes) == 0 { + return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms") + } + + cipher := packet.CipherFunction(candidateCiphers[0]) + // If the cipher specifed by config is a candidate, we'll use that. + configuredCipher := config.Cipher() + for _, c := range candidateCiphers { + cipherFunc := packet.CipherFunction(c) + if cipherFunc == configuredCipher { + cipher = cipherFunc + break + } + } + + var hash crypto.Hash + for _, hashId := range candidateHashes { + if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() { + hash = h + break + } + } + + // If the hash specified by config is a candidate, we'll use that. + if configuredHash := config.Hash(); configuredHash.Available() { + for _, hashId := range candidateHashes { + if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash { + hash = h + break + } + } + } + + if hash == 0 { + hashId := candidateHashes[0] + name, ok := s2k.HashIdToString(hashId) + if !ok { + name = "#" + strconv.Itoa(int(hashId)) + } + return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)") + } + + symKey := make([]byte, cipher.KeySize()) + if _, err := io.ReadFull(config.Random(), symKey); err != nil { + return nil, err + } + + for _, key := range encryptKeys { + if err := packet.SerializeEncryptedKey(ciphertext, key.PublicKey, cipher, symKey, config); err != nil { + return nil, err + } + } + + encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config) + if err != nil { + return + } + + if signer != nil { + ops := &packet.OnePassSignature{ + SigType: packet.SigTypeBinary, + Hash: hash, + PubKeyAlgo: signer.PubKeyAlgo, + KeyId: signer.KeyId, + IsLast: true, + } + if err := ops.Serialize(encryptedData); err != nil { + return nil, err + } + } + + if hints == nil { + hints = &FileHints{} + } + + w := encryptedData + if signer != nil { + // If we need to write a signature packet after the literal + // data then we need to stop literalData from closing + // encryptedData. + w = noOpCloser{encryptedData} + + } + var epochSeconds uint32 + if !hints.ModTime.IsZero() { + epochSeconds = uint32(hints.ModTime.Unix()) + } + literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds) + if err != nil { + return nil, err + } + + if signer != nil { + return signatureWriter{encryptedData, literalData, hash, hash.New(), signer, config}, nil + } + return literalData, nil +} + +// signatureWriter hashes the contents of a message while passing it along to +// literalData. When closed, it closes literalData, writes a signature packet +// to encryptedData and then also closes encryptedData. +type signatureWriter struct { + encryptedData io.WriteCloser + literalData io.WriteCloser + hashType crypto.Hash + h hash.Hash + signer *packet.PrivateKey + config *packet.Config +} + +func (s signatureWriter) Write(data []byte) (int, error) { + s.h.Write(data) + return s.literalData.Write(data) +} + +func (s signatureWriter) Close() error { + sig := &packet.Signature{ + SigType: packet.SigTypeBinary, + PubKeyAlgo: s.signer.PubKeyAlgo, + Hash: s.hashType, + CreationTime: s.config.Now(), + IssuerKeyId: &s.signer.KeyId, + } + + if err := sig.Sign(s.h, s.signer, s.config); err != nil { + return err + } + if err := s.literalData.Close(); err != nil { + return err + } + if err := sig.Serialize(s.encryptedData); err != nil { + return err + } + return s.encryptedData.Close() +} + +// noOpCloser is like an ioutil.NopCloser, but for an io.Writer. +// TODO: we have two of these in OpenPGP packages alone. This probably needs +// to be promoted somewhere more common. +type noOpCloser struct { + w io.Writer +} + +func (c noOpCloser) Write(data []byte) (n int, err error) { + return c.w.Write(data) +} + +func (c noOpCloser) Close() error { + return nil +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/openpgp/write_test.go b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/write_test.go new file mode 100644 index 00000000..9f8c358b --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/openpgp/write_test.go @@ -0,0 +1,234 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package openpgp + +import ( + "bytes" + "io" + "io/ioutil" + "testing" + "time" +) + +func TestSignDetached(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) + out := bytes.NewBuffer(nil) + message := bytes.NewBufferString(signedInput) + err := DetachSign(out, kring[0], message, nil) + if err != nil { + t.Error(err) + } + + testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId) +} + +func TestSignTextDetached(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) + out := bytes.NewBuffer(nil) + message := bytes.NewBufferString(signedInput) + err := DetachSignText(out, kring[0], message, nil) + if err != nil { + t.Error(err) + } + + testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId) +} + +func TestSignDetachedDSA(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyPrivateHex)) + out := bytes.NewBuffer(nil) + message := bytes.NewBufferString(signedInput) + err := DetachSign(out, kring[0], message, nil) + if err != nil { + t.Error(err) + } + + testDetachedSignature(t, kring, out, signedInput, "check", testKey3KeyId) +} + +func TestNewEntity(t *testing.T) { + if testing.Short() { + return + } + + e, err := NewEntity("Test User", "test", "test@example.com", nil) + if err != nil { + t.Errorf("failed to create entity: %s", err) + return + } + + w := bytes.NewBuffer(nil) + if err := e.SerializePrivate(w, nil); err != nil { + t.Errorf("failed to serialize entity: %s", err) + return + } + serialized := w.Bytes() + + el, err := ReadKeyRing(w) + if err != nil { + t.Errorf("failed to reparse entity: %s", err) + return + } + + if len(el) != 1 { + t.Errorf("wrong number of entities found, got %d, want 1", len(el)) + } + + w = bytes.NewBuffer(nil) + if err := e.SerializePrivate(w, nil); err != nil { + t.Errorf("failed to serialize entity second time: %s", err) + return + } + + if !bytes.Equal(w.Bytes(), serialized) { + t.Errorf("results differed") + } +} + +func TestSymmetricEncryption(t *testing.T) { + buf := new(bytes.Buffer) + plaintext, err := SymmetricallyEncrypt(buf, []byte("testing"), nil, nil) + if err != nil { + t.Errorf("error writing headers: %s", err) + return + } + message := []byte("hello world\n") + _, err = plaintext.Write(message) + if err != nil { + t.Errorf("error writing to plaintext writer: %s", err) + } + err = plaintext.Close() + if err != nil { + t.Errorf("error closing plaintext writer: %s", err) + } + + md, err := ReadMessage(buf, nil, func(keys []Key, symmetric bool) ([]byte, error) { + return []byte("testing"), nil + }, nil) + if err != nil { + t.Errorf("error rereading message: %s", err) + } + messageBuf := bytes.NewBuffer(nil) + _, err = io.Copy(messageBuf, md.UnverifiedBody) + if err != nil { + t.Errorf("error rereading message: %s", err) + } + if !bytes.Equal(message, messageBuf.Bytes()) { + t.Errorf("recovered message incorrect got '%s', want '%s'", messageBuf.Bytes(), message) + } +} + +var testEncryptionTests = []struct { + keyRingHex string + isSigned bool +}{ + { + testKeys1And2PrivateHex, + false, + }, + { + testKeys1And2PrivateHex, + true, + }, + { + dsaElGamalTestKeysHex, + false, + }, + { + dsaElGamalTestKeysHex, + true, + }, +} + +func TestEncryption(t *testing.T) { + for i, test := range testEncryptionTests { + kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex)) + + passphrase := []byte("passphrase") + for _, entity := range kring { + if entity.PrivateKey != nil && entity.PrivateKey.Encrypted { + err := entity.PrivateKey.Decrypt(passphrase) + if err != nil { + t.Errorf("#%d: failed to decrypt key", i) + } + } + for _, subkey := range entity.Subkeys { + if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted { + err := subkey.PrivateKey.Decrypt(passphrase) + if err != nil { + t.Errorf("#%d: failed to decrypt subkey", i) + } + } + } + } + + var signed *Entity + if test.isSigned { + signed = kring[0] + } + + buf := new(bytes.Buffer) + w, err := Encrypt(buf, kring[:1], signed, nil /* no hints */, nil) + if err != nil { + t.Errorf("#%d: error in Encrypt: %s", i, err) + continue + } + + const message = "testing" + _, err = w.Write([]byte(message)) + if err != nil { + t.Errorf("#%d: error writing plaintext: %s", i, err) + continue + } + err = w.Close() + if err != nil { + t.Errorf("#%d: error closing WriteCloser: %s", i, err) + continue + } + + md, err := ReadMessage(buf, kring, nil /* no prompt */, nil) + if err != nil { + t.Errorf("#%d: error reading message: %s", i, err) + continue + } + + testTime, _ := time.Parse("2006-01-02", "2013-07-01") + if test.isSigned { + signKey, _ := kring[0].signingKey(testTime) + expectedKeyId := signKey.PublicKey.KeyId + if md.SignedByKeyId != expectedKeyId { + t.Errorf("#%d: message signed by wrong key id, got: %d, want: %d", i, *md.SignedBy, expectedKeyId) + } + if md.SignedBy == nil { + t.Errorf("#%d: failed to find the signing Entity", i) + } + } + + plaintext, err := ioutil.ReadAll(md.UnverifiedBody) + if err != nil { + t.Errorf("#%d: error reading encrypted contents: %s", i, err) + continue + } + + encryptKey, _ := kring[0].encryptionKey(testTime) + expectedKeyId := encryptKey.PublicKey.KeyId + if len(md.EncryptedToKeyIds) != 1 || md.EncryptedToKeyIds[0] != expectedKeyId { + t.Errorf("#%d: expected message to be encrypted to %v, but got %#v", i, expectedKeyId, md.EncryptedToKeyIds) + } + + if string(plaintext) != message { + t.Errorf("#%d: got: %s, want: %s", i, string(plaintext), message) + } + + if test.isSigned { + if md.SignatureError != nil { + t.Errorf("#%d: signature error: %s", i, md.SignatureError) + } + if md.Signature == nil { + t.Error("signature missing") + } + } + } +} diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/LICENSE b/Godeps/_workspace/src/gopkg.in/yaml.v2/LICENSE new file mode 100644 index 00000000..a68e67f0 --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/LICENSE @@ -0,0 +1,188 @@ + +Copyright (c) 2011-2014 - Canonical Inc. + +This software is licensed under the LGPLv3, included below. + +As a special exception to the GNU Lesser General Public License version 3 +("LGPL3"), the copyright holders of this Library give you permission to +convey to a third party a Combined Work that links statically or dynamically +to this Library without providing any Minimal Corresponding Source or +Minimal Application Code as set out in 4d or providing the installation +information set out in section 4e, provided that you comply with the other +provisions of LGPL3 and provided that you meet, for the Application the +terms and conditions of the license(s) which apply to the Application. + +Except as stated in this special exception, the provisions of LGPL3 will +continue to comply in full to this Library. If you modify this Library, you +may apply this exception to your version of this Library, but you are not +obliged to do so. If you do not wish to do so, delete this exception +statement from your version. This exception does not (and cannot) modify any +license terms which apply to the Application, with which you must still +comply. + + + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/LICENSE.libyaml b/Godeps/_workspace/src/gopkg.in/yaml.v2/LICENSE.libyaml new file mode 100644 index 00000000..8da58fbf --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/LICENSE.libyaml @@ -0,0 +1,31 @@ +The following files were ported to Go from C files of libyaml, and thus +are still covered by their original copyright and license: + + apic.go + emitterc.go + parserc.go + readerc.go + scannerc.go + writerc.go + yamlh.go + yamlprivateh.go + +Copyright (c) 2006 Kirill Simonov + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/README.md b/Godeps/_workspace/src/gopkg.in/yaml.v2/README.md new file mode 100644 index 00000000..d6c919e6 --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/README.md @@ -0,0 +1,128 @@ +# YAML support for the Go language + +Introduction +------------ + +The yaml package enables Go programs to comfortably encode and decode YAML +values. It was developed within [Canonical](https://www.canonical.com) as +part of the [juju](https://juju.ubuntu.com) project, and is based on a +pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) +C library to parse and generate YAML data quickly and reliably. + +Compatibility +------------- + +The yaml package supports most of YAML 1.1 and 1.2, including support for +anchors, tags, map merging, etc. Multi-document unmarshalling is not yet +implemented, and base-60 floats from YAML 1.1 are purposefully not +supported since they're a poor design and are gone in YAML 1.2. + +Installation and usage +---------------------- + +The import path for the package is *gopkg.in/yaml.v2*. + +To install it, run: + + go get gopkg.in/yaml.v2 + +API documentation +----------------- + +If opened in a browser, the import path itself leads to the API documentation: + + * [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2) + +API stability +------------- + +The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in). + + +License +------- + +The yaml package is licensed under the LGPL with an exception that allows it to be linked statically. Please see the LICENSE file for details. + + +Example +------- + +```Go +package main + +import ( + "fmt" + "log" + + "gopkg.in/yaml.v2" +) + +var data = ` +a: Easy! +b: + c: 2 + d: [3, 4] +` + +type T struct { + A string + B struct{C int; D []int ",flow"} +} + +func main() { + t := T{} + + err := yaml.Unmarshal([]byte(data), &t) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- t:\n%v\n\n", t) + + d, err := yaml.Marshal(&t) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- t dump:\n%s\n\n", string(d)) + + m := make(map[interface{}]interface{}) + + err = yaml.Unmarshal([]byte(data), &m) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- m:\n%v\n\n", m) + + d, err = yaml.Marshal(&m) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- m dump:\n%s\n\n", string(d)) +} +``` + +This example will generate the following output: + +``` +--- t: +{Easy! {2 [3 4]}} + +--- t dump: +a: Easy! +b: + c: 2 + d: [3, 4] + + +--- m: +map[a:Easy! b:map[c:2 d:[3 4]]] + +--- m dump: +a: Easy! +b: + c: 2 + d: + - 3 + - 4 +``` + diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/apic.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/apic.go new file mode 100644 index 00000000..95ec014e --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/apic.go @@ -0,0 +1,742 @@ +package yaml + +import ( + "io" + "os" +) + +func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) { + //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens)) + + // Check if we can move the queue at the beginning of the buffer. + if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) { + if parser.tokens_head != len(parser.tokens) { + copy(parser.tokens, parser.tokens[parser.tokens_head:]) + } + parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head] + parser.tokens_head = 0 + } + parser.tokens = append(parser.tokens, *token) + if pos < 0 { + return + } + copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:]) + parser.tokens[parser.tokens_head+pos] = *token +} + +// Create a new parser object. +func yaml_parser_initialize(parser *yaml_parser_t) bool { + *parser = yaml_parser_t{ + raw_buffer: make([]byte, 0, input_raw_buffer_size), + buffer: make([]byte, 0, input_buffer_size), + } + return true +} + +// Destroy a parser object. +func yaml_parser_delete(parser *yaml_parser_t) { + *parser = yaml_parser_t{} +} + +// String read handler. +func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { + if parser.input_pos == len(parser.input) { + return 0, io.EOF + } + n = copy(buffer, parser.input[parser.input_pos:]) + parser.input_pos += n + return n, nil +} + +// File read handler. +func yaml_file_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { + return parser.input_file.Read(buffer) +} + +// Set a string input. +func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) { + if parser.read_handler != nil { + panic("must set the input source only once") + } + parser.read_handler = yaml_string_read_handler + parser.input = input + parser.input_pos = 0 +} + +// Set a file input. +func yaml_parser_set_input_file(parser *yaml_parser_t, file *os.File) { + if parser.read_handler != nil { + panic("must set the input source only once") + } + parser.read_handler = yaml_file_read_handler + parser.input_file = file +} + +// Set the source encoding. +func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) { + if parser.encoding != yaml_ANY_ENCODING { + panic("must set the encoding only once") + } + parser.encoding = encoding +} + +// Create a new emitter object. +func yaml_emitter_initialize(emitter *yaml_emitter_t) bool { + *emitter = yaml_emitter_t{ + buffer: make([]byte, output_buffer_size), + raw_buffer: make([]byte, 0, output_raw_buffer_size), + states: make([]yaml_emitter_state_t, 0, initial_stack_size), + events: make([]yaml_event_t, 0, initial_queue_size), + } + return true +} + +// Destroy an emitter object. +func yaml_emitter_delete(emitter *yaml_emitter_t) { + *emitter = yaml_emitter_t{} +} + +// String write handler. +func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error { + *emitter.output_buffer = append(*emitter.output_buffer, buffer...) + return nil +} + +// File write handler. +func yaml_file_write_handler(emitter *yaml_emitter_t, buffer []byte) error { + _, err := emitter.output_file.Write(buffer) + return err +} + +// Set a string output. +func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) { + if emitter.write_handler != nil { + panic("must set the output target only once") + } + emitter.write_handler = yaml_string_write_handler + emitter.output_buffer = output_buffer +} + +// Set a file output. +func yaml_emitter_set_output_file(emitter *yaml_emitter_t, file io.Writer) { + if emitter.write_handler != nil { + panic("must set the output target only once") + } + emitter.write_handler = yaml_file_write_handler + emitter.output_file = file +} + +// Set the output encoding. +func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) { + if emitter.encoding != yaml_ANY_ENCODING { + panic("must set the output encoding only once") + } + emitter.encoding = encoding +} + +// Set the canonical output style. +func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) { + emitter.canonical = canonical +} + +//// Set the indentation increment. +func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) { + if indent < 2 || indent > 9 { + indent = 2 + } + emitter.best_indent = indent +} + +// Set the preferred line width. +func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) { + if width < 0 { + width = -1 + } + emitter.best_width = width +} + +// Set if unescaped non-ASCII characters are allowed. +func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) { + emitter.unicode = unicode +} + +// Set the preferred line break character. +func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) { + emitter.line_break = line_break +} + +///* +// * Destroy a token object. +// */ +// +//YAML_DECLARE(void) +//yaml_token_delete(yaml_token_t *token) +//{ +// assert(token); // Non-NULL token object expected. +// +// switch (token.type) +// { +// case YAML_TAG_DIRECTIVE_TOKEN: +// yaml_free(token.data.tag_directive.handle); +// yaml_free(token.data.tag_directive.prefix); +// break; +// +// case YAML_ALIAS_TOKEN: +// yaml_free(token.data.alias.value); +// break; +// +// case YAML_ANCHOR_TOKEN: +// yaml_free(token.data.anchor.value); +// break; +// +// case YAML_TAG_TOKEN: +// yaml_free(token.data.tag.handle); +// yaml_free(token.data.tag.suffix); +// break; +// +// case YAML_SCALAR_TOKEN: +// yaml_free(token.data.scalar.value); +// break; +// +// default: +// break; +// } +// +// memset(token, 0, sizeof(yaml_token_t)); +//} +// +///* +// * Check if a string is a valid UTF-8 sequence. +// * +// * Check 'reader.c' for more details on UTF-8 encoding. +// */ +// +//static int +//yaml_check_utf8(yaml_char_t *start, size_t length) +//{ +// yaml_char_t *end = start+length; +// yaml_char_t *pointer = start; +// +// while (pointer < end) { +// unsigned char octet; +// unsigned int width; +// unsigned int value; +// size_t k; +// +// octet = pointer[0]; +// width = (octet & 0x80) == 0x00 ? 1 : +// (octet & 0xE0) == 0xC0 ? 2 : +// (octet & 0xF0) == 0xE0 ? 3 : +// (octet & 0xF8) == 0xF0 ? 4 : 0; +// value = (octet & 0x80) == 0x00 ? octet & 0x7F : +// (octet & 0xE0) == 0xC0 ? octet & 0x1F : +// (octet & 0xF0) == 0xE0 ? octet & 0x0F : +// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; +// if (!width) return 0; +// if (pointer+width > end) return 0; +// for (k = 1; k < width; k ++) { +// octet = pointer[k]; +// if ((octet & 0xC0) != 0x80) return 0; +// value = (value << 6) + (octet & 0x3F); +// } +// if (!((width == 1) || +// (width == 2 && value >= 0x80) || +// (width == 3 && value >= 0x800) || +// (width == 4 && value >= 0x10000))) return 0; +// +// pointer += width; +// } +// +// return 1; +//} +// + +// Create STREAM-START. +func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) bool { + *event = yaml_event_t{ + typ: yaml_STREAM_START_EVENT, + encoding: encoding, + } + return true +} + +// Create STREAM-END. +func yaml_stream_end_event_initialize(event *yaml_event_t) bool { + *event = yaml_event_t{ + typ: yaml_STREAM_END_EVENT, + } + return true +} + +// Create DOCUMENT-START. +func yaml_document_start_event_initialize(event *yaml_event_t, version_directive *yaml_version_directive_t, + tag_directives []yaml_tag_directive_t, implicit bool) bool { + *event = yaml_event_t{ + typ: yaml_DOCUMENT_START_EVENT, + version_directive: version_directive, + tag_directives: tag_directives, + implicit: implicit, + } + return true +} + +// Create DOCUMENT-END. +func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) bool { + *event = yaml_event_t{ + typ: yaml_DOCUMENT_END_EVENT, + implicit: implicit, + } + return true +} + +///* +// * Create ALIAS. +// */ +// +//YAML_DECLARE(int) +//yaml_alias_event_initialize(event *yaml_event_t, anchor *yaml_char_t) +//{ +// mark yaml_mark_t = { 0, 0, 0 } +// anchor_copy *yaml_char_t = NULL +// +// assert(event) // Non-NULL event object is expected. +// assert(anchor) // Non-NULL anchor is expected. +// +// if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0 +// +// anchor_copy = yaml_strdup(anchor) +// if (!anchor_copy) +// return 0 +// +// ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark) +// +// return 1 +//} + +// Create SCALAR. +func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool { + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + anchor: anchor, + tag: tag, + value: value, + implicit: plain_implicit, + quoted_implicit: quoted_implicit, + style: yaml_style_t(style), + } + return true +} + +// Create SEQUENCE-START. +func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool { + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(style), + } + return true +} + +// Create SEQUENCE-END. +func yaml_sequence_end_event_initialize(event *yaml_event_t) bool { + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + } + return true +} + +// Create MAPPING-START. +func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) bool { + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(style), + } + return true +} + +// Create MAPPING-END. +func yaml_mapping_end_event_initialize(event *yaml_event_t) bool { + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + } + return true +} + +// Destroy an event object. +func yaml_event_delete(event *yaml_event_t) { + *event = yaml_event_t{} +} + +///* +// * Create a document object. +// */ +// +//YAML_DECLARE(int) +//yaml_document_initialize(document *yaml_document_t, +// version_directive *yaml_version_directive_t, +// tag_directives_start *yaml_tag_directive_t, +// tag_directives_end *yaml_tag_directive_t, +// start_implicit int, end_implicit int) +//{ +// struct { +// error yaml_error_type_t +// } context +// struct { +// start *yaml_node_t +// end *yaml_node_t +// top *yaml_node_t +// } nodes = { NULL, NULL, NULL } +// version_directive_copy *yaml_version_directive_t = NULL +// struct { +// start *yaml_tag_directive_t +// end *yaml_tag_directive_t +// top *yaml_tag_directive_t +// } tag_directives_copy = { NULL, NULL, NULL } +// value yaml_tag_directive_t = { NULL, NULL } +// mark yaml_mark_t = { 0, 0, 0 } +// +// assert(document) // Non-NULL document object is expected. +// assert((tag_directives_start && tag_directives_end) || +// (tag_directives_start == tag_directives_end)) +// // Valid tag directives are expected. +// +// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error +// +// if (version_directive) { +// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t)) +// if (!version_directive_copy) goto error +// version_directive_copy.major = version_directive.major +// version_directive_copy.minor = version_directive.minor +// } +// +// if (tag_directives_start != tag_directives_end) { +// tag_directive *yaml_tag_directive_t +// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) +// goto error +// for (tag_directive = tag_directives_start +// tag_directive != tag_directives_end; tag_directive ++) { +// assert(tag_directive.handle) +// assert(tag_directive.prefix) +// if (!yaml_check_utf8(tag_directive.handle, +// strlen((char *)tag_directive.handle))) +// goto error +// if (!yaml_check_utf8(tag_directive.prefix, +// strlen((char *)tag_directive.prefix))) +// goto error +// value.handle = yaml_strdup(tag_directive.handle) +// value.prefix = yaml_strdup(tag_directive.prefix) +// if (!value.handle || !value.prefix) goto error +// if (!PUSH(&context, tag_directives_copy, value)) +// goto error +// value.handle = NULL +// value.prefix = NULL +// } +// } +// +// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy, +// tag_directives_copy.start, tag_directives_copy.top, +// start_implicit, end_implicit, mark, mark) +// +// return 1 +// +//error: +// STACK_DEL(&context, nodes) +// yaml_free(version_directive_copy) +// while (!STACK_EMPTY(&context, tag_directives_copy)) { +// value yaml_tag_directive_t = POP(&context, tag_directives_copy) +// yaml_free(value.handle) +// yaml_free(value.prefix) +// } +// STACK_DEL(&context, tag_directives_copy) +// yaml_free(value.handle) +// yaml_free(value.prefix) +// +// return 0 +//} +// +///* +// * Destroy a document object. +// */ +// +//YAML_DECLARE(void) +//yaml_document_delete(document *yaml_document_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// tag_directive *yaml_tag_directive_t +// +// context.error = YAML_NO_ERROR // Eliminate a compliler warning. +// +// assert(document) // Non-NULL document object is expected. +// +// while (!STACK_EMPTY(&context, document.nodes)) { +// node yaml_node_t = POP(&context, document.nodes) +// yaml_free(node.tag) +// switch (node.type) { +// case YAML_SCALAR_NODE: +// yaml_free(node.data.scalar.value) +// break +// case YAML_SEQUENCE_NODE: +// STACK_DEL(&context, node.data.sequence.items) +// break +// case YAML_MAPPING_NODE: +// STACK_DEL(&context, node.data.mapping.pairs) +// break +// default: +// assert(0) // Should not happen. +// } +// } +// STACK_DEL(&context, document.nodes) +// +// yaml_free(document.version_directive) +// for (tag_directive = document.tag_directives.start +// tag_directive != document.tag_directives.end +// tag_directive++) { +// yaml_free(tag_directive.handle) +// yaml_free(tag_directive.prefix) +// } +// yaml_free(document.tag_directives.start) +// +// memset(document, 0, sizeof(yaml_document_t)) +//} +// +///** +// * Get a document node. +// */ +// +//YAML_DECLARE(yaml_node_t *) +//yaml_document_get_node(document *yaml_document_t, index int) +//{ +// assert(document) // Non-NULL document object is expected. +// +// if (index > 0 && document.nodes.start + index <= document.nodes.top) { +// return document.nodes.start + index - 1 +// } +// return NULL +//} +// +///** +// * Get the root object. +// */ +// +//YAML_DECLARE(yaml_node_t *) +//yaml_document_get_root_node(document *yaml_document_t) +//{ +// assert(document) // Non-NULL document object is expected. +// +// if (document.nodes.top != document.nodes.start) { +// return document.nodes.start +// } +// return NULL +//} +// +///* +// * Add a scalar node to a document. +// */ +// +//YAML_DECLARE(int) +//yaml_document_add_scalar(document *yaml_document_t, +// tag *yaml_char_t, value *yaml_char_t, length int, +// style yaml_scalar_style_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// mark yaml_mark_t = { 0, 0, 0 } +// tag_copy *yaml_char_t = NULL +// value_copy *yaml_char_t = NULL +// node yaml_node_t +// +// assert(document) // Non-NULL document object is expected. +// assert(value) // Non-NULL value is expected. +// +// if (!tag) { +// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG +// } +// +// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error +// tag_copy = yaml_strdup(tag) +// if (!tag_copy) goto error +// +// if (length < 0) { +// length = strlen((char *)value) +// } +// +// if (!yaml_check_utf8(value, length)) goto error +// value_copy = yaml_malloc(length+1) +// if (!value_copy) goto error +// memcpy(value_copy, value, length) +// value_copy[length] = '\0' +// +// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark) +// if (!PUSH(&context, document.nodes, node)) goto error +// +// return document.nodes.top - document.nodes.start +// +//error: +// yaml_free(tag_copy) +// yaml_free(value_copy) +// +// return 0 +//} +// +///* +// * Add a sequence node to a document. +// */ +// +//YAML_DECLARE(int) +//yaml_document_add_sequence(document *yaml_document_t, +// tag *yaml_char_t, style yaml_sequence_style_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// mark yaml_mark_t = { 0, 0, 0 } +// tag_copy *yaml_char_t = NULL +// struct { +// start *yaml_node_item_t +// end *yaml_node_item_t +// top *yaml_node_item_t +// } items = { NULL, NULL, NULL } +// node yaml_node_t +// +// assert(document) // Non-NULL document object is expected. +// +// if (!tag) { +// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG +// } +// +// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error +// tag_copy = yaml_strdup(tag) +// if (!tag_copy) goto error +// +// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error +// +// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end, +// style, mark, mark) +// if (!PUSH(&context, document.nodes, node)) goto error +// +// return document.nodes.top - document.nodes.start +// +//error: +// STACK_DEL(&context, items) +// yaml_free(tag_copy) +// +// return 0 +//} +// +///* +// * Add a mapping node to a document. +// */ +// +//YAML_DECLARE(int) +//yaml_document_add_mapping(document *yaml_document_t, +// tag *yaml_char_t, style yaml_mapping_style_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// mark yaml_mark_t = { 0, 0, 0 } +// tag_copy *yaml_char_t = NULL +// struct { +// start *yaml_node_pair_t +// end *yaml_node_pair_t +// top *yaml_node_pair_t +// } pairs = { NULL, NULL, NULL } +// node yaml_node_t +// +// assert(document) // Non-NULL document object is expected. +// +// if (!tag) { +// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG +// } +// +// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error +// tag_copy = yaml_strdup(tag) +// if (!tag_copy) goto error +// +// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error +// +// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end, +// style, mark, mark) +// if (!PUSH(&context, document.nodes, node)) goto error +// +// return document.nodes.top - document.nodes.start +// +//error: +// STACK_DEL(&context, pairs) +// yaml_free(tag_copy) +// +// return 0 +//} +// +///* +// * Append an item to a sequence node. +// */ +// +//YAML_DECLARE(int) +//yaml_document_append_sequence_item(document *yaml_document_t, +// sequence int, item int) +//{ +// struct { +// error yaml_error_type_t +// } context +// +// assert(document) // Non-NULL document is required. +// assert(sequence > 0 +// && document.nodes.start + sequence <= document.nodes.top) +// // Valid sequence id is required. +// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE) +// // A sequence node is required. +// assert(item > 0 && document.nodes.start + item <= document.nodes.top) +// // Valid item id is required. +// +// if (!PUSH(&context, +// document.nodes.start[sequence-1].data.sequence.items, item)) +// return 0 +// +// return 1 +//} +// +///* +// * Append a pair of a key and a value to a mapping node. +// */ +// +//YAML_DECLARE(int) +//yaml_document_append_mapping_pair(document *yaml_document_t, +// mapping int, key int, value int) +//{ +// struct { +// error yaml_error_type_t +// } context +// +// pair yaml_node_pair_t +// +// assert(document) // Non-NULL document is required. +// assert(mapping > 0 +// && document.nodes.start + mapping <= document.nodes.top) +// // Valid mapping id is required. +// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE) +// // A mapping node is required. +// assert(key > 0 && document.nodes.start + key <= document.nodes.top) +// // Valid key id is required. +// assert(value > 0 && document.nodes.start + value <= document.nodes.top) +// // Valid value id is required. +// +// pair.key = key +// pair.value = value +// +// if (!PUSH(&context, +// document.nodes.start[mapping-1].data.mapping.pairs, pair)) +// return 0 +// +// return 1 +//} +// +// diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/decode.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/decode.go new file mode 100644 index 00000000..085cddc4 --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/decode.go @@ -0,0 +1,683 @@ +package yaml + +import ( + "encoding" + "encoding/base64" + "fmt" + "math" + "reflect" + "strconv" + "time" +) + +const ( + documentNode = 1 << iota + mappingNode + sequenceNode + scalarNode + aliasNode +) + +type node struct { + kind int + line, column int + tag string + value string + implicit bool + children []*node + anchors map[string]*node +} + +// ---------------------------------------------------------------------------- +// Parser, produces a node tree out of a libyaml event stream. + +type parser struct { + parser yaml_parser_t + event yaml_event_t + doc *node +} + +func newParser(b []byte) *parser { + p := parser{} + if !yaml_parser_initialize(&p.parser) { + panic("failed to initialize YAML emitter") + } + + if len(b) == 0 { + b = []byte{'\n'} + } + + yaml_parser_set_input_string(&p.parser, b) + + p.skip() + if p.event.typ != yaml_STREAM_START_EVENT { + panic("expected stream start event, got " + strconv.Itoa(int(p.event.typ))) + } + p.skip() + return &p +} + +func (p *parser) destroy() { + if p.event.typ != yaml_NO_EVENT { + yaml_event_delete(&p.event) + } + yaml_parser_delete(&p.parser) +} + +func (p *parser) skip() { + if p.event.typ != yaml_NO_EVENT { + if p.event.typ == yaml_STREAM_END_EVENT { + failf("attempted to go past the end of stream; corrupted value?") + } + yaml_event_delete(&p.event) + } + if !yaml_parser_parse(&p.parser, &p.event) { + p.fail() + } +} + +func (p *parser) fail() { + var where string + var line int + if p.parser.problem_mark.line != 0 { + line = p.parser.problem_mark.line + } else if p.parser.context_mark.line != 0 { + line = p.parser.context_mark.line + } + if line != 0 { + where = "line " + strconv.Itoa(line) + ": " + } + var msg string + if len(p.parser.problem) > 0 { + msg = p.parser.problem + } else { + msg = "unknown problem parsing YAML content" + } + failf("%s%s", where, msg) +} + +func (p *parser) anchor(n *node, anchor []byte) { + if anchor != nil { + p.doc.anchors[string(anchor)] = n + } +} + +func (p *parser) parse() *node { + switch p.event.typ { + case yaml_SCALAR_EVENT: + return p.scalar() + case yaml_ALIAS_EVENT: + return p.alias() + case yaml_MAPPING_START_EVENT: + return p.mapping() + case yaml_SEQUENCE_START_EVENT: + return p.sequence() + case yaml_DOCUMENT_START_EVENT: + return p.document() + case yaml_STREAM_END_EVENT: + // Happens when attempting to decode an empty buffer. + return nil + default: + panic("attempted to parse unknown event: " + strconv.Itoa(int(p.event.typ))) + } + panic("unreachable") +} + +func (p *parser) node(kind int) *node { + return &node{ + kind: kind, + line: p.event.start_mark.line, + column: p.event.start_mark.column, + } +} + +func (p *parser) document() *node { + n := p.node(documentNode) + n.anchors = make(map[string]*node) + p.doc = n + p.skip() + n.children = append(n.children, p.parse()) + if p.event.typ != yaml_DOCUMENT_END_EVENT { + panic("expected end of document event but got " + strconv.Itoa(int(p.event.typ))) + } + p.skip() + return n +} + +func (p *parser) alias() *node { + n := p.node(aliasNode) + n.value = string(p.event.anchor) + p.skip() + return n +} + +func (p *parser) scalar() *node { + n := p.node(scalarNode) + n.value = string(p.event.value) + n.tag = string(p.event.tag) + n.implicit = p.event.implicit + p.anchor(n, p.event.anchor) + p.skip() + return n +} + +func (p *parser) sequence() *node { + n := p.node(sequenceNode) + p.anchor(n, p.event.anchor) + p.skip() + for p.event.typ != yaml_SEQUENCE_END_EVENT { + n.children = append(n.children, p.parse()) + } + p.skip() + return n +} + +func (p *parser) mapping() *node { + n := p.node(mappingNode) + p.anchor(n, p.event.anchor) + p.skip() + for p.event.typ != yaml_MAPPING_END_EVENT { + n.children = append(n.children, p.parse(), p.parse()) + } + p.skip() + return n +} + +// ---------------------------------------------------------------------------- +// Decoder, unmarshals a node into a provided value. + +type decoder struct { + doc *node + aliases map[string]bool + mapType reflect.Type + terrors []string +} + +var ( + mapItemType = reflect.TypeOf(MapItem{}) + durationType = reflect.TypeOf(time.Duration(0)) + defaultMapType = reflect.TypeOf(map[interface{}]interface{}{}) + ifaceType = defaultMapType.Elem() +) + +func newDecoder() *decoder { + d := &decoder{mapType: defaultMapType} + d.aliases = make(map[string]bool) + return d +} + +func (d *decoder) terror(n *node, tag string, out reflect.Value) { + if n.tag != "" { + tag = n.tag + } + value := n.value + if tag != yaml_SEQ_TAG && tag != yaml_MAP_TAG { + if len(value) > 10 { + value = " `" + value[:7] + "...`" + } else { + value = " `" + value + "`" + } + } + d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.line+1, shortTag(tag), value, out.Type())) +} + +func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) { + terrlen := len(d.terrors) + err := u.UnmarshalYAML(func(v interface{}) (err error) { + defer handleErr(&err) + d.unmarshal(n, reflect.ValueOf(v)) + if len(d.terrors) > terrlen { + issues := d.terrors[terrlen:] + d.terrors = d.terrors[:terrlen] + return &TypeError{issues} + } + return nil + }) + if e, ok := err.(*TypeError); ok { + d.terrors = append(d.terrors, e.Errors...) + return false + } + if err != nil { + fail(err) + } + return true +} + +// d.prepare initializes and dereferences pointers and calls UnmarshalYAML +// if a value is found to implement it. +// It returns the initialized and dereferenced out value, whether +// unmarshalling was already done by UnmarshalYAML, and if so whether +// its types unmarshalled appropriately. +// +// If n holds a null value, prepare returns before doing anything. +func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) { + if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "") { + return out, false, false + } + again := true + for again { + again = false + if out.Kind() == reflect.Ptr { + if out.IsNil() { + out.Set(reflect.New(out.Type().Elem())) + } + out = out.Elem() + again = true + } + if out.CanAddr() { + if u, ok := out.Addr().Interface().(Unmarshaler); ok { + good = d.callUnmarshaler(n, u) + return out, true, good + } + } + } + return out, false, false +} + +func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) { + switch n.kind { + case documentNode: + return d.document(n, out) + case aliasNode: + return d.alias(n, out) + } + out, unmarshaled, good := d.prepare(n, out) + if unmarshaled { + return good + } + switch n.kind { + case scalarNode: + good = d.scalar(n, out) + case mappingNode: + good = d.mapping(n, out) + case sequenceNode: + good = d.sequence(n, out) + default: + panic("internal error: unknown node kind: " + strconv.Itoa(n.kind)) + } + return good +} + +func (d *decoder) document(n *node, out reflect.Value) (good bool) { + if len(n.children) == 1 { + d.doc = n + d.unmarshal(n.children[0], out) + return true + } + return false +} + +func (d *decoder) alias(n *node, out reflect.Value) (good bool) { + an, ok := d.doc.anchors[n.value] + if !ok { + failf("unknown anchor '%s' referenced", n.value) + } + if d.aliases[n.value] { + failf("anchor '%s' value contains itself", n.value) + } + d.aliases[n.value] = true + good = d.unmarshal(an, out) + delete(d.aliases, n.value) + return good +} + +var zeroValue reflect.Value + +func resetMap(out reflect.Value) { + for _, k := range out.MapKeys() { + out.SetMapIndex(k, zeroValue) + } +} + +func (d *decoder) scalar(n *node, out reflect.Value) (good bool) { + var tag string + var resolved interface{} + if n.tag == "" && !n.implicit { + tag = yaml_STR_TAG + resolved = n.value + } else { + tag, resolved = resolve(n.tag, n.value) + if tag == yaml_BINARY_TAG { + data, err := base64.StdEncoding.DecodeString(resolved.(string)) + if err != nil { + failf("!!binary value contains invalid base64 data") + } + resolved = string(data) + } + } + if resolved == nil { + if out.Kind() == reflect.Map && !out.CanAddr() { + resetMap(out) + } else { + out.Set(reflect.Zero(out.Type())) + } + return true + } + if s, ok := resolved.(string); ok && out.CanAddr() { + if u, ok := out.Addr().Interface().(encoding.TextUnmarshaler); ok { + err := u.UnmarshalText([]byte(s)) + if err != nil { + fail(err) + } + return true + } + } + switch out.Kind() { + case reflect.String: + if tag == yaml_BINARY_TAG { + out.SetString(resolved.(string)) + good = true + } else if resolved != nil { + out.SetString(n.value) + good = true + } + case reflect.Interface: + if resolved == nil { + out.Set(reflect.Zero(out.Type())) + } else { + out.Set(reflect.ValueOf(resolved)) + } + good = true + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + switch resolved := resolved.(type) { + case int: + if !out.OverflowInt(int64(resolved)) { + out.SetInt(int64(resolved)) + good = true + } + case int64: + if !out.OverflowInt(resolved) { + out.SetInt(resolved) + good = true + } + case uint64: + if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { + out.SetInt(int64(resolved)) + good = true + } + case float64: + if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { + out.SetInt(int64(resolved)) + good = true + } + case string: + if out.Type() == durationType { + d, err := time.ParseDuration(resolved) + if err == nil { + out.SetInt(int64(d)) + good = true + } + } + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + switch resolved := resolved.(type) { + case int: + if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + good = true + } + case int64: + if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + good = true + } + case uint64: + if !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + good = true + } + case float64: + if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + good = true + } + } + case reflect.Bool: + switch resolved := resolved.(type) { + case bool: + out.SetBool(resolved) + good = true + } + case reflect.Float32, reflect.Float64: + switch resolved := resolved.(type) { + case int: + out.SetFloat(float64(resolved)) + good = true + case int64: + out.SetFloat(float64(resolved)) + good = true + case uint64: + out.SetFloat(float64(resolved)) + good = true + case float64: + out.SetFloat(resolved) + good = true + } + case reflect.Ptr: + if out.Type().Elem() == reflect.TypeOf(resolved) { + // TODO DOes this make sense? When is out a Ptr except when decoding a nil value? + elem := reflect.New(out.Type().Elem()) + elem.Elem().Set(reflect.ValueOf(resolved)) + out.Set(elem) + good = true + } + } + if !good { + d.terror(n, tag, out) + } + return good +} + +func settableValueOf(i interface{}) reflect.Value { + v := reflect.ValueOf(i) + sv := reflect.New(v.Type()).Elem() + sv.Set(v) + return sv +} + +func (d *decoder) sequence(n *node, out reflect.Value) (good bool) { + l := len(n.children) + + var iface reflect.Value + switch out.Kind() { + case reflect.Slice: + out.Set(reflect.MakeSlice(out.Type(), l, l)) + case reflect.Interface: + // No type hints. Will have to use a generic sequence. + iface = out + out = settableValueOf(make([]interface{}, l)) + default: + d.terror(n, yaml_SEQ_TAG, out) + return false + } + et := out.Type().Elem() + + j := 0 + for i := 0; i < l; i++ { + e := reflect.New(et).Elem() + if ok := d.unmarshal(n.children[i], e); ok { + out.Index(j).Set(e) + j++ + } + } + out.Set(out.Slice(0, j)) + if iface.IsValid() { + iface.Set(out) + } + return true +} + +func (d *decoder) mapping(n *node, out reflect.Value) (good bool) { + switch out.Kind() { + case reflect.Struct: + return d.mappingStruct(n, out) + case reflect.Slice: + return d.mappingSlice(n, out) + case reflect.Map: + // okay + case reflect.Interface: + if d.mapType.Kind() == reflect.Map { + iface := out + out = reflect.MakeMap(d.mapType) + iface.Set(out) + } else { + slicev := reflect.New(d.mapType).Elem() + if !d.mappingSlice(n, slicev) { + return false + } + out.Set(slicev) + return true + } + default: + d.terror(n, yaml_MAP_TAG, out) + return false + } + outt := out.Type() + kt := outt.Key() + et := outt.Elem() + + mapType := d.mapType + if outt.Key() == ifaceType && outt.Elem() == ifaceType { + d.mapType = outt + } + + if out.IsNil() { + out.Set(reflect.MakeMap(outt)) + } + l := len(n.children) + for i := 0; i < l; i += 2 { + if isMerge(n.children[i]) { + d.merge(n.children[i+1], out) + continue + } + k := reflect.New(kt).Elem() + if d.unmarshal(n.children[i], k) { + kkind := k.Kind() + if kkind == reflect.Interface { + kkind = k.Elem().Kind() + } + if kkind == reflect.Map || kkind == reflect.Slice { + failf("invalid map key: %#v", k.Interface()) + } + e := reflect.New(et).Elem() + if d.unmarshal(n.children[i+1], e) { + out.SetMapIndex(k, e) + } + } + } + d.mapType = mapType + return true +} + +func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) { + outt := out.Type() + if outt.Elem() != mapItemType { + d.terror(n, yaml_MAP_TAG, out) + return false + } + + mapType := d.mapType + d.mapType = outt + + var slice []MapItem + var l = len(n.children) + for i := 0; i < l; i += 2 { + if isMerge(n.children[i]) { + d.merge(n.children[i+1], out) + continue + } + item := MapItem{} + k := reflect.ValueOf(&item.Key).Elem() + if d.unmarshal(n.children[i], k) { + v := reflect.ValueOf(&item.Value).Elem() + if d.unmarshal(n.children[i+1], v) { + slice = append(slice, item) + } + } + } + out.Set(reflect.ValueOf(slice)) + d.mapType = mapType + return true +} + +func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) { + sinfo, err := getStructInfo(out.Type()) + if err != nil { + panic(err) + } + name := settableValueOf("") + l := len(n.children) + + var inlineMap reflect.Value + var elemType reflect.Type + if sinfo.InlineMap != -1 { + inlineMap = out.Field(sinfo.InlineMap) + inlineMap.Set(reflect.New(inlineMap.Type()).Elem()) + elemType = inlineMap.Type().Elem() + } + + for i := 0; i < l; i += 2 { + ni := n.children[i] + if isMerge(ni) { + d.merge(n.children[i+1], out) + continue + } + if !d.unmarshal(ni, name) { + continue + } + if info, ok := sinfo.FieldsMap[name.String()]; ok { + var field reflect.Value + if info.Inline == nil { + field = out.Field(info.Num) + } else { + field = out.FieldByIndex(info.Inline) + } + d.unmarshal(n.children[i+1], field) + } else if sinfo.InlineMap != -1 { + if inlineMap.IsNil() { + inlineMap.Set(reflect.MakeMap(inlineMap.Type())) + } + value := reflect.New(elemType).Elem() + d.unmarshal(n.children[i+1], value) + inlineMap.SetMapIndex(name, value) + } + } + return true +} + +func failWantMap() { + failf("map merge requires map or sequence of maps as the value") +} + +func (d *decoder) merge(n *node, out reflect.Value) { + switch n.kind { + case mappingNode: + d.unmarshal(n, out) + case aliasNode: + an, ok := d.doc.anchors[n.value] + if ok && an.kind != mappingNode { + failWantMap() + } + d.unmarshal(n, out) + case sequenceNode: + // Step backwards as earlier nodes take precedence. + for i := len(n.children) - 1; i >= 0; i-- { + ni := n.children[i] + if ni.kind == aliasNode { + an, ok := d.doc.anchors[ni.value] + if ok && an.kind != mappingNode { + failWantMap() + } + } else if ni.kind != mappingNode { + failWantMap() + } + d.unmarshal(ni, out) + } + default: + failWantMap() + } +} + +func isMerge(n *node) bool { + return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG) +} diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/decode_test.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/decode_test.go new file mode 100644 index 00000000..c25b11ab --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/decode_test.go @@ -0,0 +1,966 @@ +package yaml_test + +import ( + "errors" + "github.com/khlieng/name_pending/Godeps/_workspace/src/gopkg.in/yaml.v2" + . "gopkg.in/check.v1" + "math" + "net" + "reflect" + "strings" + "time" +) + +var unmarshalIntTest = 123 + +var unmarshalTests = []struct { + data string + value interface{} +}{ + { + "", + &struct{}{}, + }, { + "{}", &struct{}{}, + }, { + "v: hi", + map[string]string{"v": "hi"}, + }, { + "v: hi", map[string]interface{}{"v": "hi"}, + }, { + "v: true", + map[string]string{"v": "true"}, + }, { + "v: true", + map[string]interface{}{"v": true}, + }, { + "v: 10", + map[string]interface{}{"v": 10}, + }, { + "v: 0b10", + map[string]interface{}{"v": 2}, + }, { + "v: 0xA", + map[string]interface{}{"v": 10}, + }, { + "v: 4294967296", + map[string]int64{"v": 4294967296}, + }, { + "v: 0.1", + map[string]interface{}{"v": 0.1}, + }, { + "v: .1", + map[string]interface{}{"v": 0.1}, + }, { + "v: .Inf", + map[string]interface{}{"v": math.Inf(+1)}, + }, { + "v: -.Inf", + map[string]interface{}{"v": math.Inf(-1)}, + }, { + "v: -10", + map[string]interface{}{"v": -10}, + }, { + "v: -.1", + map[string]interface{}{"v": -0.1}, + }, + + // Simple values. + { + "123", + &unmarshalIntTest, + }, + + // Floats from spec + { + "canonical: 6.8523e+5", + map[string]interface{}{"canonical": 6.8523e+5}, + }, { + "expo: 685.230_15e+03", + map[string]interface{}{"expo": 685.23015e+03}, + }, { + "fixed: 685_230.15", + map[string]interface{}{"fixed": 685230.15}, + }, { + "neginf: -.inf", + map[string]interface{}{"neginf": math.Inf(-1)}, + }, { + "fixed: 685_230.15", + map[string]float64{"fixed": 685230.15}, + }, + //{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported + //{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails. + + // Bools from spec + { + "canonical: y", + map[string]interface{}{"canonical": true}, + }, { + "answer: NO", + map[string]interface{}{"answer": false}, + }, { + "logical: True", + map[string]interface{}{"logical": true}, + }, { + "option: on", + map[string]interface{}{"option": true}, + }, { + "option: on", + map[string]bool{"option": true}, + }, + // Ints from spec + { + "canonical: 685230", + map[string]interface{}{"canonical": 685230}, + }, { + "decimal: +685_230", + map[string]interface{}{"decimal": 685230}, + }, { + "octal: 02472256", + map[string]interface{}{"octal": 685230}, + }, { + "hexa: 0x_0A_74_AE", + map[string]interface{}{"hexa": 685230}, + }, { + "bin: 0b1010_0111_0100_1010_1110", + map[string]interface{}{"bin": 685230}, + }, { + "bin: -0b101010", + map[string]interface{}{"bin": -42}, + }, { + "decimal: +685_230", + map[string]int{"decimal": 685230}, + }, + + //{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported + + // Nulls from spec + { + "empty:", + map[string]interface{}{"empty": nil}, + }, { + "canonical: ~", + map[string]interface{}{"canonical": nil}, + }, { + "english: null", + map[string]interface{}{"english": nil}, + }, { + "~: null key", + map[interface{}]string{nil: "null key"}, + }, { + "empty:", + map[string]*bool{"empty": nil}, + }, + + // Flow sequence + { + "seq: [A,B]", + map[string]interface{}{"seq": []interface{}{"A", "B"}}, + }, { + "seq: [A,B,C,]", + map[string][]string{"seq": []string{"A", "B", "C"}}, + }, { + "seq: [A,1,C]", + map[string][]string{"seq": []string{"A", "1", "C"}}, + }, { + "seq: [A,1,C]", + map[string][]int{"seq": []int{1}}, + }, { + "seq: [A,1,C]", + map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, + }, + // Block sequence + { + "seq:\n - A\n - B", + map[string]interface{}{"seq": []interface{}{"A", "B"}}, + }, { + "seq:\n - A\n - B\n - C", + map[string][]string{"seq": []string{"A", "B", "C"}}, + }, { + "seq:\n - A\n - 1\n - C", + map[string][]string{"seq": []string{"A", "1", "C"}}, + }, { + "seq:\n - A\n - 1\n - C", + map[string][]int{"seq": []int{1}}, + }, { + "seq:\n - A\n - 1\n - C", + map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, + }, + + // Literal block scalar + { + "scalar: | # Comment\n\n literal\n\n \ttext\n\n", + map[string]string{"scalar": "\nliteral\n\n\ttext\n"}, + }, + + // Folded block scalar + { + "scalar: > # Comment\n\n folded\n line\n \n next\n line\n * one\n * two\n\n last\n line\n\n", + map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"}, + }, + + // Map inside interface with no type hints. + { + "a: {b: c}", + map[interface{}]interface{}{"a": map[interface{}]interface{}{"b": "c"}}, + }, + + // Structs and type conversions. + { + "hello: world", + &struct{ Hello string }{"world"}, + }, { + "a: {b: c}", + &struct{ A struct{ B string } }{struct{ B string }{"c"}}, + }, { + "a: {b: c}", + &struct{ A *struct{ B string } }{&struct{ B string }{"c"}}, + }, { + "a: {b: c}", + &struct{ A map[string]string }{map[string]string{"b": "c"}}, + }, { + "a: {b: c}", + &struct{ A *map[string]string }{&map[string]string{"b": "c"}}, + }, { + "a:", + &struct{ A map[string]string }{}, + }, { + "a: 1", + &struct{ A int }{1}, + }, { + "a: 1", + &struct{ A float64 }{1}, + }, { + "a: 1.0", + &struct{ A int }{1}, + }, { + "a: 1.0", + &struct{ A uint }{1}, + }, { + "a: [1, 2]", + &struct{ A []int }{[]int{1, 2}}, + }, { + "a: 1", + &struct{ B int }{0}, + }, { + "a: 1", + &struct { + B int "a" + }{1}, + }, { + "a: y", + &struct{ A bool }{true}, + }, + + // Some cross type conversions + { + "v: 42", + map[string]uint{"v": 42}, + }, { + "v: -42", + map[string]uint{}, + }, { + "v: 4294967296", + map[string]uint64{"v": 4294967296}, + }, { + "v: -4294967296", + map[string]uint64{}, + }, + + // int + { + "int_max: 2147483647", + map[string]int{"int_max": math.MaxInt32}, + }, + { + "int_min: -2147483648", + map[string]int{"int_min": math.MinInt32}, + }, + { + "int_overflow: 9223372036854775808", // math.MaxInt64 + 1 + map[string]int{}, + }, + + // int64 + { + "int64_max: 9223372036854775807", + map[string]int64{"int64_max": math.MaxInt64}, + }, + { + "int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111", + map[string]int64{"int64_max_base2": math.MaxInt64}, + }, + { + "int64_min: -9223372036854775808", + map[string]int64{"int64_min": math.MinInt64}, + }, + { + "int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111", + map[string]int64{"int64_neg_base2": -math.MaxInt64}, + }, + { + "int64_overflow: 9223372036854775808", // math.MaxInt64 + 1 + map[string]int64{}, + }, + + // uint + { + "uint_min: 0", + map[string]uint{"uint_min": 0}, + }, + { + "uint_max: 4294967295", + map[string]uint{"uint_max": math.MaxUint32}, + }, + { + "uint_underflow: -1", + map[string]uint{}, + }, + + // uint64 + { + "uint64_min: 0", + map[string]uint{"uint64_min": 0}, + }, + { + "uint64_max: 18446744073709551615", + map[string]uint64{"uint64_max": math.MaxUint64}, + }, + { + "uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111", + map[string]uint64{"uint64_max_base2": math.MaxUint64}, + }, + { + "uint64_maxint64: 9223372036854775807", + map[string]uint64{"uint64_maxint64": math.MaxInt64}, + }, + { + "uint64_underflow: -1", + map[string]uint64{}, + }, + + // float32 + { + "float32_max: 3.40282346638528859811704183484516925440e+38", + map[string]float32{"float32_max": math.MaxFloat32}, + }, + { + "float32_nonzero: 1.401298464324817070923729583289916131280e-45", + map[string]float32{"float32_nonzero": math.SmallestNonzeroFloat32}, + }, + { + "float32_maxuint64: 18446744073709551615", + map[string]float32{"float32_maxuint64": float32(math.MaxUint64)}, + }, + { + "float32_maxuint64+1: 18446744073709551616", + map[string]float32{"float32_maxuint64+1": float32(math.MaxUint64 + 1)}, + }, + + // float64 + { + "float64_max: 1.797693134862315708145274237317043567981e+308", + map[string]float64{"float64_max": math.MaxFloat64}, + }, + { + "float64_nonzero: 4.940656458412465441765687928682213723651e-324", + map[string]float64{"float64_nonzero": math.SmallestNonzeroFloat64}, + }, + { + "float64_maxuint64: 18446744073709551615", + map[string]float64{"float64_maxuint64": float64(math.MaxUint64)}, + }, + { + "float64_maxuint64+1: 18446744073709551616", + map[string]float64{"float64_maxuint64+1": float64(math.MaxUint64 + 1)}, + }, + + // Overflow cases. + { + "v: 4294967297", + map[string]int32{}, + }, { + "v: 128", + map[string]int8{}, + }, + + // Quoted values. + { + "'1': '\"2\"'", + map[interface{}]interface{}{"1": "\"2\""}, + }, { + "v:\n- A\n- 'B\n\n C'\n", + map[string][]string{"v": []string{"A", "B\nC"}}, + }, + + // Explicit tags. + { + "v: !!float '1.1'", + map[string]interface{}{"v": 1.1}, + }, { + "v: !!null ''", + map[string]interface{}{"v": nil}, + }, { + "%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'", + map[string]interface{}{"v": 1}, + }, + + // Anchors and aliases. + { + "a: &x 1\nb: &y 2\nc: *x\nd: *y\n", + &struct{ A, B, C, D int }{1, 2, 1, 2}, + }, { + "a: &a {c: 1}\nb: *a", + &struct { + A, B struct { + C int + } + }{struct{ C int }{1}, struct{ C int }{1}}, + }, { + "a: &a [1, 2]\nb: *a", + &struct{ B []int }{[]int{1, 2}}, + }, { + "b: *a\na: &a {c: 1}", + &struct { + A, B struct { + C int + } + }{struct{ C int }{1}, struct{ C int }{1}}, + }, + + // Bug #1133337 + { + "foo: ''", + map[string]*string{"foo": new(string)}, + }, { + "foo: null", + map[string]string{"foo": ""}, + }, { + "foo: null", + map[string]interface{}{"foo": nil}, + }, + + // Ignored field + { + "a: 1\nb: 2\n", + &struct { + A int + B int "-" + }{1, 0}, + }, + + // Bug #1191981 + { + "" + + "%YAML 1.1\n" + + "--- !!str\n" + + `"Generic line break (no glyph)\n\` + "\n" + + ` Generic line break (glyphed)\n\` + "\n" + + ` Line separator\u2028\` + "\n" + + ` Paragraph separator\u2029"` + "\n", + "" + + "Generic line break (no glyph)\n" + + "Generic line break (glyphed)\n" + + "Line separator\u2028Paragraph separator\u2029", + }, + + // Struct inlining + { + "a: 1\nb: 2\nc: 3\n", + &struct { + A int + C inlineB `yaml:",inline"` + }{1, inlineB{2, inlineC{3}}}, + }, + + // Map inlining + { + "a: 1\nb: 2\nc: 3\n", + &struct { + A int + C map[string]int `yaml:",inline"` + }{1, map[string]int{"b": 2, "c": 3}}, + }, + + // bug 1243827 + { + "a: -b_c", + map[string]interface{}{"a": "-b_c"}, + }, + { + "a: +b_c", + map[string]interface{}{"a": "+b_c"}, + }, + { + "a: 50cent_of_dollar", + map[string]interface{}{"a": "50cent_of_dollar"}, + }, + + // Duration + { + "a: 3s", + map[string]time.Duration{"a": 3 * time.Second}, + }, + + // Issue #24. + { + "a: ", + map[string]string{"a": ""}, + }, + + // Base 60 floats are obsolete and unsupported. + { + "a: 1:1\n", + map[string]string{"a": "1:1"}, + }, + + // Binary data. + { + "a: !!binary gIGC\n", + map[string]string{"a": "\x80\x81\x82"}, + }, { + "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n", + map[string]string{"a": strings.Repeat("\x90", 54)}, + }, { + "a: !!binary |\n " + strings.Repeat("A", 70) + "\n ==\n", + map[string]string{"a": strings.Repeat("\x00", 52)}, + }, + + // Ordered maps. + { + "{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}", + &yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}}, + }, + + // Issue #39. + { + "a:\n b:\n c: d\n", + map[string]struct{ B interface{} }{"a": {map[interface{}]interface{}{"c": "d"}}}, + }, + + // Custom map type. + { + "a: {b: c}", + M{"a": M{"b": "c"}}, + }, + + // Support encoding.TextUnmarshaler. + { + "a: 1.2.3.4\n", + map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)}, + }, + { + "a: 2015-02-24T18:19:39Z\n", + map[string]time.Time{"a": time.Unix(1424801979, 0)}, + }, + + // Encode empty lists as zero-length slices. + { + "a: []", + &struct{ A []int }{[]int{}}, + }, +} + +type M map[interface{}]interface{} + +type inlineB struct { + B int + inlineC `yaml:",inline"` +} + +type inlineC struct { + C int +} + +func (s *S) TestUnmarshal(c *C) { + for _, item := range unmarshalTests { + t := reflect.ValueOf(item.value).Type() + var value interface{} + switch t.Kind() { + case reflect.Map: + value = reflect.MakeMap(t).Interface() + case reflect.String: + value = reflect.New(t).Interface() + case reflect.Ptr: + value = reflect.New(t.Elem()).Interface() + default: + c.Fatalf("missing case for %s", t) + } + err := yaml.Unmarshal([]byte(item.data), value) + if _, ok := err.(*yaml.TypeError); !ok { + c.Assert(err, IsNil) + } + if t.Kind() == reflect.String { + c.Assert(*value.(*string), Equals, item.value) + } else { + c.Assert(value, DeepEquals, item.value) + } + } +} + +func (s *S) TestUnmarshalNaN(c *C) { + value := map[string]interface{}{} + err := yaml.Unmarshal([]byte("notanum: .NaN"), &value) + c.Assert(err, IsNil) + c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true) +} + +var unmarshalErrorTests = []struct { + data, error string +}{ + {"v: !!float 'error'", "yaml: cannot decode !!str `error` as a !!float"}, + {"v: [A,", "yaml: line 1: did not find expected node content"}, + {"v:\n- [A,", "yaml: line 2: did not find expected node content"}, + {"a: *b\n", "yaml: unknown anchor 'b' referenced"}, + {"a: &a\n b: *a\n", "yaml: anchor 'a' value contains itself"}, + {"value: -", "yaml: block sequence entries are not allowed in this context"}, + {"a: !!binary ==", "yaml: !!binary value contains invalid base64 data"}, + {"{[.]}", `yaml: invalid map key: \[\]interface \{\}\{"\."\}`}, + {"{{.}}", `yaml: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`}, +} + +func (s *S) TestUnmarshalErrors(c *C) { + for _, item := range unmarshalErrorTests { + var value interface{} + err := yaml.Unmarshal([]byte(item.data), &value) + c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value)) + } +} + +var unmarshalerTests = []struct { + data, tag string + value interface{} +}{ + {"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}}, + {"_: [1,A]", "!!seq", []interface{}{1, "A"}}, + {"_: 10", "!!int", 10}, + {"_: null", "!!null", nil}, + {`_: BAR!`, "!!str", "BAR!"}, + {`_: "BAR!"`, "!!str", "BAR!"}, + {"_: !!foo 'BAR!'", "!!foo", "BAR!"}, +} + +var unmarshalerResult = map[int]error{} + +type unmarshalerType struct { + value interface{} +} + +func (o *unmarshalerType) UnmarshalYAML(unmarshal func(v interface{}) error) error { + if err := unmarshal(&o.value); err != nil { + return err + } + if i, ok := o.value.(int); ok { + if result, ok := unmarshalerResult[i]; ok { + return result + } + } + return nil +} + +type unmarshalerPointer struct { + Field *unmarshalerType "_" +} + +type unmarshalerValue struct { + Field unmarshalerType "_" +} + +func (s *S) TestUnmarshalerPointerField(c *C) { + for _, item := range unmarshalerTests { + obj := &unmarshalerPointer{} + err := yaml.Unmarshal([]byte(item.data), obj) + c.Assert(err, IsNil) + if item.value == nil { + c.Assert(obj.Field, IsNil) + } else { + c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) + c.Assert(obj.Field.value, DeepEquals, item.value) + } + } +} + +func (s *S) TestUnmarshalerValueField(c *C) { + for _, item := range unmarshalerTests { + obj := &unmarshalerValue{} + err := yaml.Unmarshal([]byte(item.data), obj) + c.Assert(err, IsNil) + c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) + c.Assert(obj.Field.value, DeepEquals, item.value) + } +} + +func (s *S) TestUnmarshalerWholeDocument(c *C) { + obj := &unmarshalerType{} + err := yaml.Unmarshal([]byte(unmarshalerTests[0].data), obj) + c.Assert(err, IsNil) + value, ok := obj.value.(map[interface{}]interface{}) + c.Assert(ok, Equals, true, Commentf("value: %#v", obj.value)) + c.Assert(value["_"], DeepEquals, unmarshalerTests[0].value) +} + +func (s *S) TestUnmarshalerTypeError(c *C) { + unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}} + unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}} + defer func() { + delete(unmarshalerResult, 2) + delete(unmarshalerResult, 4) + }() + + type T struct { + Before int + After int + M map[string]*unmarshalerType + } + var v T + data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}` + err := yaml.Unmarshal([]byte(data), &v) + c.Assert(err, ErrorMatches, ""+ + "yaml: unmarshal errors:\n"+ + " line 1: cannot unmarshal !!str `A` into int\n"+ + " foo\n"+ + " bar\n"+ + " line 1: cannot unmarshal !!str `B` into int") + c.Assert(v.M["abc"], NotNil) + c.Assert(v.M["def"], IsNil) + c.Assert(v.M["ghi"], NotNil) + c.Assert(v.M["jkl"], IsNil) + + c.Assert(v.M["abc"].value, Equals, 1) + c.Assert(v.M["ghi"].value, Equals, 3) +} + +type proxyTypeError struct{} + +func (v *proxyTypeError) UnmarshalYAML(unmarshal func(interface{}) error) error { + var s string + var a int32 + var b int64 + if err := unmarshal(&s); err != nil { + panic(err) + } + if s == "a" { + if err := unmarshal(&b); err == nil { + panic("should have failed") + } + return unmarshal(&a) + } + if err := unmarshal(&a); err == nil { + panic("should have failed") + } + return unmarshal(&b) +} + +func (s *S) TestUnmarshalerTypeErrorProxying(c *C) { + type T struct { + Before int + After int + M map[string]*proxyTypeError + } + var v T + data := `{before: A, m: {abc: a, def: b}, after: B}` + err := yaml.Unmarshal([]byte(data), &v) + c.Assert(err, ErrorMatches, ""+ + "yaml: unmarshal errors:\n"+ + " line 1: cannot unmarshal !!str `A` into int\n"+ + " line 1: cannot unmarshal !!str `a` into int32\n"+ + " line 1: cannot unmarshal !!str `b` into int64\n"+ + " line 1: cannot unmarshal !!str `B` into int") +} + +type failingUnmarshaler struct{} + +var failingErr = errors.New("failingErr") + +func (ft *failingUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error { + return failingErr +} + +func (s *S) TestUnmarshalerError(c *C) { + err := yaml.Unmarshal([]byte("a: b"), &failingUnmarshaler{}) + c.Assert(err, Equals, failingErr) +} + +type sliceUnmarshaler []int + +func (su *sliceUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error { + var slice []int + err := unmarshal(&slice) + if err == nil { + *su = slice + return nil + } + + var intVal int + err = unmarshal(&intVal) + if err == nil { + *su = []int{intVal} + return nil + } + + return err +} + +func (s *S) TestUnmarshalerRetry(c *C) { + var su sliceUnmarshaler + err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su) + c.Assert(err, IsNil) + c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1, 2, 3})) + + err = yaml.Unmarshal([]byte("1"), &su) + c.Assert(err, IsNil) + c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1})) +} + +// From http://yaml.org/type/merge.html +var mergeTests = ` +anchors: + list: + - &CENTER { "x": 1, "y": 2 } + - &LEFT { "x": 0, "y": 2 } + - &BIG { "r": 10 } + - &SMALL { "r": 1 } + +# All the following maps are equal: + +plain: + # Explicit keys + "x": 1 + "y": 2 + "r": 10 + label: center/big + +mergeOne: + # Merge one map + << : *CENTER + "r": 10 + label: center/big + +mergeMultiple: + # Merge multiple maps + << : [ *CENTER, *BIG ] + label: center/big + +override: + # Override + << : [ *BIG, *LEFT, *SMALL ] + "x": 1 + label: center/big + +shortTag: + # Explicit short merge tag + !!merge "<<" : [ *CENTER, *BIG ] + label: center/big + +longTag: + # Explicit merge long tag + ! "<<" : [ *CENTER, *BIG ] + label: center/big + +inlineMap: + # Inlined map + << : {"x": 1, "y": 2, "r": 10} + label: center/big + +inlineSequenceMap: + # Inlined map in sequence + << : [ *CENTER, {"r": 10} ] + label: center/big +` + +func (s *S) TestMerge(c *C) { + var want = map[interface{}]interface{}{ + "x": 1, + "y": 2, + "r": 10, + "label": "center/big", + } + + var m map[interface{}]interface{} + err := yaml.Unmarshal([]byte(mergeTests), &m) + c.Assert(err, IsNil) + for name, test := range m { + if name == "anchors" { + continue + } + c.Assert(test, DeepEquals, want, Commentf("test %q failed", name)) + } +} + +func (s *S) TestMergeStruct(c *C) { + type Data struct { + X, Y, R int + Label string + } + want := Data{1, 2, 10, "center/big"} + + var m map[string]Data + err := yaml.Unmarshal([]byte(mergeTests), &m) + c.Assert(err, IsNil) + for name, test := range m { + if name == "anchors" { + continue + } + c.Assert(test, Equals, want, Commentf("test %q failed", name)) + } +} + +var unmarshalNullTests = []func() interface{}{ + func() interface{} { var v interface{}; v = "v"; return &v }, + func() interface{} { var s = "s"; return &s }, + func() interface{} { var s = "s"; sptr := &s; return &sptr }, + func() interface{} { var i = 1; return &i }, + func() interface{} { var i = 1; iptr := &i; return &iptr }, + func() interface{} { m := map[string]int{"s": 1}; return &m }, + func() interface{} { m := map[string]int{"s": 1}; return m }, +} + +func (s *S) TestUnmarshalNull(c *C) { + for _, test := range unmarshalNullTests { + item := test() + zero := reflect.Zero(reflect.TypeOf(item).Elem()).Interface() + err := yaml.Unmarshal([]byte("null"), item) + c.Assert(err, IsNil) + if reflect.TypeOf(item).Kind() == reflect.Map { + c.Assert(reflect.ValueOf(item).Interface(), DeepEquals, reflect.MakeMap(reflect.TypeOf(item)).Interface()) + } else { + c.Assert(reflect.ValueOf(item).Elem().Interface(), DeepEquals, zero) + } + } +} + +func (s *S) TestUnmarshalSliceOnPreset(c *C) { + // Issue #48. + v := struct{ A []int }{[]int{1}} + yaml.Unmarshal([]byte("a: [2]"), &v) + c.Assert(v.A, DeepEquals, []int{2}) +} + +//var data []byte +//func init() { +// var err error +// data, err = ioutil.ReadFile("/tmp/file.yaml") +// if err != nil { +// panic(err) +// } +//} +// +//func (s *S) BenchmarkUnmarshal(c *C) { +// var err error +// for i := 0; i < c.N; i++ { +// var v map[string]interface{} +// err = yaml.Unmarshal(data, &v) +// } +// if err != nil { +// panic(err) +// } +//} +// +//func (s *S) BenchmarkMarshal(c *C) { +// var v map[string]interface{} +// yaml.Unmarshal(data, &v) +// c.ResetTimer() +// for i := 0; i < c.N; i++ { +// yaml.Marshal(&v) +// } +//} diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/emitterc.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/emitterc.go new file mode 100644 index 00000000..9b3dc4a4 --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/emitterc.go @@ -0,0 +1,1685 @@ +package yaml + +import ( + "bytes" +) + +// Flush the buffer if needed. +func flush(emitter *yaml_emitter_t) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) { + return yaml_emitter_flush(emitter) + } + return true +} + +// Put a character to the output buffer. +func put(emitter *yaml_emitter_t, value byte) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { + return false + } + emitter.buffer[emitter.buffer_pos] = value + emitter.buffer_pos++ + emitter.column++ + return true +} + +// Put a line break to the output buffer. +func put_break(emitter *yaml_emitter_t) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { + return false + } + switch emitter.line_break { + case yaml_CR_BREAK: + emitter.buffer[emitter.buffer_pos] = '\r' + emitter.buffer_pos += 1 + case yaml_LN_BREAK: + emitter.buffer[emitter.buffer_pos] = '\n' + emitter.buffer_pos += 1 + case yaml_CRLN_BREAK: + emitter.buffer[emitter.buffer_pos+0] = '\r' + emitter.buffer[emitter.buffer_pos+1] = '\n' + emitter.buffer_pos += 2 + default: + panic("unknown line break setting") + } + emitter.column = 0 + emitter.line++ + return true +} + +// Copy a character from a string into buffer. +func write(emitter *yaml_emitter_t, s []byte, i *int) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { + return false + } + p := emitter.buffer_pos + w := width(s[*i]) + switch w { + case 4: + emitter.buffer[p+3] = s[*i+3] + fallthrough + case 3: + emitter.buffer[p+2] = s[*i+2] + fallthrough + case 2: + emitter.buffer[p+1] = s[*i+1] + fallthrough + case 1: + emitter.buffer[p+0] = s[*i+0] + default: + panic("unknown character width") + } + emitter.column++ + emitter.buffer_pos += w + *i += w + return true +} + +// Write a whole string into buffer. +func write_all(emitter *yaml_emitter_t, s []byte) bool { + for i := 0; i < len(s); { + if !write(emitter, s, &i) { + return false + } + } + return true +} + +// Copy a line break character from a string into buffer. +func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool { + if s[*i] == '\n' { + if !put_break(emitter) { + return false + } + *i++ + } else { + if !write(emitter, s, i) { + return false + } + emitter.column = 0 + emitter.line++ + } + return true +} + +// Set an emitter error and return false. +func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool { + emitter.error = yaml_EMITTER_ERROR + emitter.problem = problem + return false +} + +// Emit an event. +func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool { + emitter.events = append(emitter.events, *event) + for !yaml_emitter_need_more_events(emitter) { + event := &emitter.events[emitter.events_head] + if !yaml_emitter_analyze_event(emitter, event) { + return false + } + if !yaml_emitter_state_machine(emitter, event) { + return false + } + yaml_event_delete(event) + emitter.events_head++ + } + return true +} + +// Check if we need to accumulate more events before emitting. +// +// We accumulate extra +// - 1 event for DOCUMENT-START +// - 2 events for SEQUENCE-START +// - 3 events for MAPPING-START +// +func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool { + if emitter.events_head == len(emitter.events) { + return true + } + var accumulate int + switch emitter.events[emitter.events_head].typ { + case yaml_DOCUMENT_START_EVENT: + accumulate = 1 + break + case yaml_SEQUENCE_START_EVENT: + accumulate = 2 + break + case yaml_MAPPING_START_EVENT: + accumulate = 3 + break + default: + return false + } + if len(emitter.events)-emitter.events_head > accumulate { + return false + } + var level int + for i := emitter.events_head; i < len(emitter.events); i++ { + switch emitter.events[i].typ { + case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT: + level++ + case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT: + level-- + } + if level == 0 { + return false + } + } + return true +} + +// Append a directive to the directives stack. +func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool { + for i := 0; i < len(emitter.tag_directives); i++ { + if bytes.Equal(value.handle, emitter.tag_directives[i].handle) { + if allow_duplicates { + return true + } + return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive") + } + } + + // [Go] Do we actually need to copy this given garbage collection + // and the lack of deallocating destructors? + tag_copy := yaml_tag_directive_t{ + handle: make([]byte, len(value.handle)), + prefix: make([]byte, len(value.prefix)), + } + copy(tag_copy.handle, value.handle) + copy(tag_copy.prefix, value.prefix) + emitter.tag_directives = append(emitter.tag_directives, tag_copy) + return true +} + +// Increase the indentation level. +func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool { + emitter.indents = append(emitter.indents, emitter.indent) + if emitter.indent < 0 { + if flow { + emitter.indent = emitter.best_indent + } else { + emitter.indent = 0 + } + } else if !indentless { + emitter.indent += emitter.best_indent + } + return true +} + +// State dispatcher. +func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool { + switch emitter.state { + default: + case yaml_EMIT_STREAM_START_STATE: + return yaml_emitter_emit_stream_start(emitter, event) + + case yaml_EMIT_FIRST_DOCUMENT_START_STATE: + return yaml_emitter_emit_document_start(emitter, event, true) + + case yaml_EMIT_DOCUMENT_START_STATE: + return yaml_emitter_emit_document_start(emitter, event, false) + + case yaml_EMIT_DOCUMENT_CONTENT_STATE: + return yaml_emitter_emit_document_content(emitter, event) + + case yaml_EMIT_DOCUMENT_END_STATE: + return yaml_emitter_emit_document_end(emitter, event) + + case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE: + return yaml_emitter_emit_flow_sequence_item(emitter, event, true) + + case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE: + return yaml_emitter_emit_flow_sequence_item(emitter, event, false) + + case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE: + return yaml_emitter_emit_flow_mapping_key(emitter, event, true) + + case yaml_EMIT_FLOW_MAPPING_KEY_STATE: + return yaml_emitter_emit_flow_mapping_key(emitter, event, false) + + case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE: + return yaml_emitter_emit_flow_mapping_value(emitter, event, true) + + case yaml_EMIT_FLOW_MAPPING_VALUE_STATE: + return yaml_emitter_emit_flow_mapping_value(emitter, event, false) + + case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE: + return yaml_emitter_emit_block_sequence_item(emitter, event, true) + + case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE: + return yaml_emitter_emit_block_sequence_item(emitter, event, false) + + case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE: + return yaml_emitter_emit_block_mapping_key(emitter, event, true) + + case yaml_EMIT_BLOCK_MAPPING_KEY_STATE: + return yaml_emitter_emit_block_mapping_key(emitter, event, false) + + case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE: + return yaml_emitter_emit_block_mapping_value(emitter, event, true) + + case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE: + return yaml_emitter_emit_block_mapping_value(emitter, event, false) + + case yaml_EMIT_END_STATE: + return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END") + } + panic("invalid emitter state") +} + +// Expect STREAM-START. +func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if event.typ != yaml_STREAM_START_EVENT { + return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START") + } + if emitter.encoding == yaml_ANY_ENCODING { + emitter.encoding = event.encoding + if emitter.encoding == yaml_ANY_ENCODING { + emitter.encoding = yaml_UTF8_ENCODING + } + } + if emitter.best_indent < 2 || emitter.best_indent > 9 { + emitter.best_indent = 2 + } + if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 { + emitter.best_width = 80 + } + if emitter.best_width < 0 { + emitter.best_width = 1<<31 - 1 + } + if emitter.line_break == yaml_ANY_BREAK { + emitter.line_break = yaml_LN_BREAK + } + + emitter.indent = -1 + emitter.line = 0 + emitter.column = 0 + emitter.whitespace = true + emitter.indention = true + + if emitter.encoding != yaml_UTF8_ENCODING { + if !yaml_emitter_write_bom(emitter) { + return false + } + } + emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE + return true +} + +// Expect DOCUMENT-START or STREAM-END. +func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + + if event.typ == yaml_DOCUMENT_START_EVENT { + + if event.version_directive != nil { + if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) { + return false + } + } + + for i := 0; i < len(event.tag_directives); i++ { + tag_directive := &event.tag_directives[i] + if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) { + return false + } + if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) { + return false + } + } + + for i := 0; i < len(default_tag_directives); i++ { + tag_directive := &default_tag_directives[i] + if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) { + return false + } + } + + implicit := event.implicit + if !first || emitter.canonical { + implicit = false + } + + if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) { + if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if event.version_directive != nil { + implicit = false + if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if len(event.tag_directives) > 0 { + implicit = false + for i := 0; i < len(event.tag_directives); i++ { + tag_directive := &event.tag_directives[i] + if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) { + return false + } + if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) { + return false + } + if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + } + + if yaml_emitter_check_empty_document(emitter) { + implicit = false + } + if !implicit { + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) { + return false + } + if emitter.canonical { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + } + + emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE + return true + } + + if event.typ == yaml_STREAM_END_EVENT { + if emitter.open_ended { + if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_flush(emitter) { + return false + } + emitter.state = yaml_EMIT_END_STATE + return true + } + + return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END") +} + +// Expect the root node. +func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool { + emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE) + return yaml_emitter_emit_node(emitter, event, true, false, false, false) +} + +// Expect DOCUMENT-END. +func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if event.typ != yaml_DOCUMENT_END_EVENT { + return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END") + } + if !yaml_emitter_write_indent(emitter) { + return false + } + if !event.implicit { + // [Go] Allocate the slice elsewhere. + if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_flush(emitter) { + return false + } + emitter.state = yaml_EMIT_DOCUMENT_START_STATE + emitter.tag_directives = emitter.tag_directives[:0] + return true +} + +// Expect a flow item node. +func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + if first { + if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) { + return false + } + if !yaml_emitter_increase_indent(emitter, true, false) { + return false + } + emitter.flow_level++ + } + + if event.typ == yaml_SEQUENCE_END_EVENT { + emitter.flow_level-- + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + if emitter.canonical && !first { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) { + return false + } + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + + return true + } + + if !first { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + + if emitter.canonical || emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE) + return yaml_emitter_emit_node(emitter, event, false, true, false, false) +} + +// Expect a flow key node. +func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + if first { + if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) { + return false + } + if !yaml_emitter_increase_indent(emitter, true, false) { + return false + } + emitter.flow_level++ + } + + if event.typ == yaml_MAPPING_END_EVENT { + emitter.flow_level-- + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + if emitter.canonical && !first { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) { + return false + } + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true + } + + if !first { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + if emitter.canonical || emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if !emitter.canonical && yaml_emitter_check_simple_key(emitter) { + emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, true) + } + if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) { + return false + } + emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, false) +} + +// Expect a flow value node. +func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { + if simple { + if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { + return false + } + } else { + if emitter.canonical || emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) { + return false + } + } + emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, false) +} + +// Expect a block item node. +func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + if first { + if !yaml_emitter_increase_indent(emitter, false, emitter.mapping_context && !emitter.indention) { + return false + } + } + if event.typ == yaml_SEQUENCE_END_EVENT { + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true + } + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) { + return false + } + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE) + return yaml_emitter_emit_node(emitter, event, false, true, false, false) +} + +// Expect a block key node. +func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + if first { + if !yaml_emitter_increase_indent(emitter, false, false) { + return false + } + } + if event.typ == yaml_MAPPING_END_EVENT { + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true + } + if !yaml_emitter_write_indent(emitter) { + return false + } + if yaml_emitter_check_simple_key(emitter) { + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, true) + } + if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) { + return false + } + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, false) +} + +// Expect a block value node. +func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { + if simple { + if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { + return false + } + } else { + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) { + return false + } + } + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, false) +} + +// Expect a node. +func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t, + root bool, sequence bool, mapping bool, simple_key bool) bool { + + emitter.root_context = root + emitter.sequence_context = sequence + emitter.mapping_context = mapping + emitter.simple_key_context = simple_key + + switch event.typ { + case yaml_ALIAS_EVENT: + return yaml_emitter_emit_alias(emitter, event) + case yaml_SCALAR_EVENT: + return yaml_emitter_emit_scalar(emitter, event) + case yaml_SEQUENCE_START_EVENT: + return yaml_emitter_emit_sequence_start(emitter, event) + case yaml_MAPPING_START_EVENT: + return yaml_emitter_emit_mapping_start(emitter, event) + default: + return yaml_emitter_set_emitter_error(emitter, + "expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS") + } + return false +} + +// Expect ALIAS. +func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_process_anchor(emitter) { + return false + } + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true +} + +// Expect SCALAR. +func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_select_scalar_style(emitter, event) { + return false + } + if !yaml_emitter_process_anchor(emitter) { + return false + } + if !yaml_emitter_process_tag(emitter) { + return false + } + if !yaml_emitter_increase_indent(emitter, true, false) { + return false + } + if !yaml_emitter_process_scalar(emitter) { + return false + } + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true +} + +// Expect SEQUENCE-START. +func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_process_anchor(emitter) { + return false + } + if !yaml_emitter_process_tag(emitter) { + return false + } + if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE || + yaml_emitter_check_empty_sequence(emitter) { + emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE + } else { + emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE + } + return true +} + +// Expect MAPPING-START. +func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_process_anchor(emitter) { + return false + } + if !yaml_emitter_process_tag(emitter) { + return false + } + if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE || + yaml_emitter_check_empty_mapping(emitter) { + emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE + } else { + emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE + } + return true +} + +// Check if the document content is an empty scalar. +func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool { + return false // [Go] Huh? +} + +// Check if the next events represent an empty sequence. +func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool { + if len(emitter.events)-emitter.events_head < 2 { + return false + } + return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT && + emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT +} + +// Check if the next events represent an empty mapping. +func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool { + if len(emitter.events)-emitter.events_head < 2 { + return false + } + return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT && + emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT +} + +// Check if the next node can be expressed as a simple key. +func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool { + length := 0 + switch emitter.events[emitter.events_head].typ { + case yaml_ALIAS_EVENT: + length += len(emitter.anchor_data.anchor) + case yaml_SCALAR_EVENT: + if emitter.scalar_data.multiline { + return false + } + length += len(emitter.anchor_data.anchor) + + len(emitter.tag_data.handle) + + len(emitter.tag_data.suffix) + + len(emitter.scalar_data.value) + case yaml_SEQUENCE_START_EVENT: + if !yaml_emitter_check_empty_sequence(emitter) { + return false + } + length += len(emitter.anchor_data.anchor) + + len(emitter.tag_data.handle) + + len(emitter.tag_data.suffix) + case yaml_MAPPING_START_EVENT: + if !yaml_emitter_check_empty_mapping(emitter) { + return false + } + length += len(emitter.anchor_data.anchor) + + len(emitter.tag_data.handle) + + len(emitter.tag_data.suffix) + default: + return false + } + return length <= 128 +} + +// Determine an acceptable scalar style. +func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool { + + no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 + if no_tag && !event.implicit && !event.quoted_implicit { + return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified") + } + + style := event.scalar_style() + if style == yaml_ANY_SCALAR_STYLE { + style = yaml_PLAIN_SCALAR_STYLE + } + if emitter.canonical { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + if emitter.simple_key_context && emitter.scalar_data.multiline { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + + if style == yaml_PLAIN_SCALAR_STYLE { + if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed || + emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed { + style = yaml_SINGLE_QUOTED_SCALAR_STYLE + } + if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) { + style = yaml_SINGLE_QUOTED_SCALAR_STYLE + } + if no_tag && !event.implicit { + style = yaml_SINGLE_QUOTED_SCALAR_STYLE + } + } + if style == yaml_SINGLE_QUOTED_SCALAR_STYLE { + if !emitter.scalar_data.single_quoted_allowed { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + } + if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE { + if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + } + + if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE { + emitter.tag_data.handle = []byte{'!'} + } + emitter.scalar_data.style = style + return true +} + +// Write an achor. +func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool { + if emitter.anchor_data.anchor == nil { + return true + } + c := []byte{'&'} + if emitter.anchor_data.alias { + c[0] = '*' + } + if !yaml_emitter_write_indicator(emitter, c, true, false, false) { + return false + } + return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor) +} + +// Write a tag. +func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool { + if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 { + return true + } + if len(emitter.tag_data.handle) > 0 { + if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) { + return false + } + if len(emitter.tag_data.suffix) > 0 { + if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { + return false + } + } + } else { + // [Go] Allocate these slices elsewhere. + if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) { + return false + } + if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) { + return false + } + } + return true +} + +// Write a scalar. +func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool { + switch emitter.scalar_data.style { + case yaml_PLAIN_SCALAR_STYLE: + return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) + + case yaml_SINGLE_QUOTED_SCALAR_STYLE: + return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) + + case yaml_DOUBLE_QUOTED_SCALAR_STYLE: + return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) + + case yaml_LITERAL_SCALAR_STYLE: + return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value) + + case yaml_FOLDED_SCALAR_STYLE: + return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value) + } + panic("unknown scalar style") +} + +// Check if a %YAML directive is valid. +func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool { + if version_directive.major != 1 || version_directive.minor != 1 { + return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive") + } + return true +} + +// Check if a %TAG directive is valid. +func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool { + handle := tag_directive.handle + prefix := tag_directive.prefix + if len(handle) == 0 { + return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty") + } + if handle[0] != '!' { + return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'") + } + if handle[len(handle)-1] != '!' { + return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'") + } + for i := 1; i < len(handle)-1; i += width(handle[i]) { + if !is_alpha(handle, i) { + return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only") + } + } + if len(prefix) == 0 { + return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty") + } + return true +} + +// Check if an anchor is valid. +func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool { + if len(anchor) == 0 { + problem := "anchor value must not be empty" + if alias { + problem = "alias value must not be empty" + } + return yaml_emitter_set_emitter_error(emitter, problem) + } + for i := 0; i < len(anchor); i += width(anchor[i]) { + if !is_alpha(anchor, i) { + problem := "anchor value must contain alphanumerical characters only" + if alias { + problem = "alias value must contain alphanumerical characters only" + } + return yaml_emitter_set_emitter_error(emitter, problem) + } + } + emitter.anchor_data.anchor = anchor + emitter.anchor_data.alias = alias + return true +} + +// Check if a tag is valid. +func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool { + if len(tag) == 0 { + return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty") + } + for i := 0; i < len(emitter.tag_directives); i++ { + tag_directive := &emitter.tag_directives[i] + if bytes.HasPrefix(tag, tag_directive.prefix) { + emitter.tag_data.handle = tag_directive.handle + emitter.tag_data.suffix = tag[len(tag_directive.prefix):] + return true + } + } + emitter.tag_data.suffix = tag + return true +} + +// Check if a scalar is valid. +func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool { + var ( + block_indicators = false + flow_indicators = false + line_breaks = false + special_characters = false + + leading_space = false + leading_break = false + trailing_space = false + trailing_break = false + break_space = false + space_break = false + + preceeded_by_whitespace = false + followed_by_whitespace = false + previous_space = false + previous_break = false + ) + + emitter.scalar_data.value = value + + if len(value) == 0 { + emitter.scalar_data.multiline = false + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = true + emitter.scalar_data.single_quoted_allowed = true + emitter.scalar_data.block_allowed = false + return true + } + + if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) { + block_indicators = true + flow_indicators = true + } + + preceeded_by_whitespace = true + for i, w := 0, 0; i < len(value); i += w { + w = width(value[0]) + followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w) + + if i == 0 { + switch value[i] { + case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`': + flow_indicators = true + block_indicators = true + case '?', ':': + flow_indicators = true + if followed_by_whitespace { + block_indicators = true + } + case '-': + if followed_by_whitespace { + flow_indicators = true + block_indicators = true + } + } + } else { + switch value[i] { + case ',', '?', '[', ']', '{', '}': + flow_indicators = true + case ':': + flow_indicators = true + if followed_by_whitespace { + block_indicators = true + } + case '#': + if preceeded_by_whitespace { + flow_indicators = true + block_indicators = true + } + } + } + + if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode { + special_characters = true + } + if is_space(value, i) { + if i == 0 { + leading_space = true + } + if i+width(value[i]) == len(value) { + trailing_space = true + } + if previous_break { + break_space = true + } + previous_space = true + previous_break = false + } else if is_break(value, i) { + line_breaks = true + if i == 0 { + leading_break = true + } + if i+width(value[i]) == len(value) { + trailing_break = true + } + if previous_space { + space_break = true + } + previous_space = false + previous_break = true + } else { + previous_space = false + previous_break = false + } + + // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition. + preceeded_by_whitespace = is_blankz(value, i) + } + + emitter.scalar_data.multiline = line_breaks + emitter.scalar_data.flow_plain_allowed = true + emitter.scalar_data.block_plain_allowed = true + emitter.scalar_data.single_quoted_allowed = true + emitter.scalar_data.block_allowed = true + + if leading_space || leading_break || trailing_space || trailing_break { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + } + if trailing_space { + emitter.scalar_data.block_allowed = false + } + if break_space { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + emitter.scalar_data.single_quoted_allowed = false + } + if space_break || special_characters { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + emitter.scalar_data.single_quoted_allowed = false + emitter.scalar_data.block_allowed = false + } + if line_breaks { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + } + if flow_indicators { + emitter.scalar_data.flow_plain_allowed = false + } + if block_indicators { + emitter.scalar_data.block_plain_allowed = false + } + return true +} + +// Check if the event data is valid. +func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { + + emitter.anchor_data.anchor = nil + emitter.tag_data.handle = nil + emitter.tag_data.suffix = nil + emitter.scalar_data.value = nil + + switch event.typ { + case yaml_ALIAS_EVENT: + if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) { + return false + } + + case yaml_SCALAR_EVENT: + if len(event.anchor) > 0 { + if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { + return false + } + } + if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) { + if !yaml_emitter_analyze_tag(emitter, event.tag) { + return false + } + } + if !yaml_emitter_analyze_scalar(emitter, event.value) { + return false + } + + case yaml_SEQUENCE_START_EVENT: + if len(event.anchor) > 0 { + if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { + return false + } + } + if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { + if !yaml_emitter_analyze_tag(emitter, event.tag) { + return false + } + } + + case yaml_MAPPING_START_EVENT: + if len(event.anchor) > 0 { + if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { + return false + } + } + if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { + if !yaml_emitter_analyze_tag(emitter, event.tag) { + return false + } + } + } + return true +} + +// Write the BOM character. +func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool { + if !flush(emitter) { + return false + } + pos := emitter.buffer_pos + emitter.buffer[pos+0] = '\xEF' + emitter.buffer[pos+1] = '\xBB' + emitter.buffer[pos+2] = '\xBF' + emitter.buffer_pos += 3 + return true +} + +func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool { + indent := emitter.indent + if indent < 0 { + indent = 0 + } + if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) { + if !put_break(emitter) { + return false + } + } + for emitter.column < indent { + if !put(emitter, ' ') { + return false + } + } + emitter.whitespace = true + emitter.indention = true + return true +} + +func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool { + if need_whitespace && !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + if !write_all(emitter, indicator) { + return false + } + emitter.whitespace = is_whitespace + emitter.indention = (emitter.indention && is_indention) + emitter.open_ended = false + return true +} + +func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool { + if !write_all(emitter, value) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool { + if !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + if !write_all(emitter, value) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool { + if need_whitespace && !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + for i := 0; i < len(value); { + var must_write bool + switch value[i] { + case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']': + must_write = true + default: + must_write = is_alpha(value, i) + } + if must_write { + if !write(emitter, value, &i) { + return false + } + } else { + w := width(value[i]) + for k := 0; k < w; k++ { + octet := value[i] + i++ + if !put(emitter, '%') { + return false + } + + c := octet >> 4 + if c < 10 { + c += '0' + } else { + c += 'A' - 10 + } + if !put(emitter, c) { + return false + } + + c = octet & 0x0f + if c < 10 { + c += '0' + } else { + c += 'A' - 10 + } + if !put(emitter, c) { + return false + } + } + } + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { + if !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + + spaces := false + breaks := false + for i := 0; i < len(value); { + if is_space(value, i) { + if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) { + if !yaml_emitter_write_indent(emitter) { + return false + } + i += width(value[i]) + } else { + if !write(emitter, value, &i) { + return false + } + } + spaces = true + } else if is_break(value, i) { + if !breaks && value[i] == '\n' { + if !put_break(emitter) { + return false + } + } + if !write_break(emitter, value, &i) { + return false + } + emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !write(emitter, value, &i) { + return false + } + emitter.indention = false + spaces = false + breaks = false + } + } + + emitter.whitespace = false + emitter.indention = false + if emitter.root_context { + emitter.open_ended = true + } + + return true +} + +func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { + + if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) { + return false + } + + spaces := false + breaks := false + for i := 0; i < len(value); { + if is_space(value, i) { + if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) { + if !yaml_emitter_write_indent(emitter) { + return false + } + i += width(value[i]) + } else { + if !write(emitter, value, &i) { + return false + } + } + spaces = true + } else if is_break(value, i) { + if !breaks && value[i] == '\n' { + if !put_break(emitter) { + return false + } + } + if !write_break(emitter, value, &i) { + return false + } + emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if value[i] == '\'' { + if !put(emitter, '\'') { + return false + } + } + if !write(emitter, value, &i) { + return false + } + emitter.indention = false + spaces = false + breaks = false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { + spaces := false + if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) { + return false + } + + for i := 0; i < len(value); { + if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) || + is_bom(value, i) || is_break(value, i) || + value[i] == '"' || value[i] == '\\' { + + octet := value[i] + + var w int + var v rune + switch { + case octet&0x80 == 0x00: + w, v = 1, rune(octet&0x7F) + case octet&0xE0 == 0xC0: + w, v = 2, rune(octet&0x1F) + case octet&0xF0 == 0xE0: + w, v = 3, rune(octet&0x0F) + case octet&0xF8 == 0xF0: + w, v = 4, rune(octet&0x07) + } + for k := 1; k < w; k++ { + octet = value[i+k] + v = (v << 6) + (rune(octet) & 0x3F) + } + i += w + + if !put(emitter, '\\') { + return false + } + + var ok bool + switch v { + case 0x00: + ok = put(emitter, '0') + case 0x07: + ok = put(emitter, 'a') + case 0x08: + ok = put(emitter, 'b') + case 0x09: + ok = put(emitter, 't') + case 0x0A: + ok = put(emitter, 'n') + case 0x0b: + ok = put(emitter, 'v') + case 0x0c: + ok = put(emitter, 'f') + case 0x0d: + ok = put(emitter, 'r') + case 0x1b: + ok = put(emitter, 'e') + case 0x22: + ok = put(emitter, '"') + case 0x5c: + ok = put(emitter, '\\') + case 0x85: + ok = put(emitter, 'N') + case 0xA0: + ok = put(emitter, '_') + case 0x2028: + ok = put(emitter, 'L') + case 0x2029: + ok = put(emitter, 'P') + default: + if v <= 0xFF { + ok = put(emitter, 'x') + w = 2 + } else if v <= 0xFFFF { + ok = put(emitter, 'u') + w = 4 + } else { + ok = put(emitter, 'U') + w = 8 + } + for k := (w - 1) * 4; ok && k >= 0; k -= 4 { + digit := byte((v >> uint(k)) & 0x0F) + if digit < 10 { + ok = put(emitter, digit+'0') + } else { + ok = put(emitter, digit+'A'-10) + } + } + } + if !ok { + return false + } + spaces = false + } else if is_space(value, i) { + if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 { + if !yaml_emitter_write_indent(emitter) { + return false + } + if is_space(value, i+1) { + if !put(emitter, '\\') { + return false + } + } + i += width(value[i]) + } else if !write(emitter, value, &i) { + return false + } + spaces = true + } else { + if !write(emitter, value, &i) { + return false + } + spaces = false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool { + if is_space(value, 0) || is_break(value, 0) { + indent_hint := []byte{'0' + byte(emitter.best_indent)} + if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) { + return false + } + } + + emitter.open_ended = false + + var chomp_hint [1]byte + if len(value) == 0 { + chomp_hint[0] = '-' + } else { + i := len(value) - 1 + for value[i]&0xC0 == 0x80 { + i-- + } + if !is_break(value, i) { + chomp_hint[0] = '-' + } else if i == 0 { + chomp_hint[0] = '+' + emitter.open_ended = true + } else { + i-- + for value[i]&0xC0 == 0x80 { + i-- + } + if is_break(value, i) { + chomp_hint[0] = '+' + emitter.open_ended = true + } + } + } + if chomp_hint[0] != 0 { + if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) { + return false + } + } + return true +} + +func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool { + if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) { + return false + } + if !yaml_emitter_write_block_scalar_hints(emitter, value) { + return false + } + if !put_break(emitter) { + return false + } + emitter.indention = true + emitter.whitespace = true + breaks := true + for i := 0; i < len(value); { + if is_break(value, i) { + if !write_break(emitter, value, &i) { + return false + } + emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !write(emitter, value, &i) { + return false + } + emitter.indention = false + breaks = false + } + } + + return true +} + +func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool { + if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) { + return false + } + if !yaml_emitter_write_block_scalar_hints(emitter, value) { + return false + } + + if !put_break(emitter) { + return false + } + emitter.indention = true + emitter.whitespace = true + + breaks := true + leading_spaces := true + for i := 0; i < len(value); { + if is_break(value, i) { + if !breaks && !leading_spaces && value[i] == '\n' { + k := 0 + for is_break(value, k) { + k += width(value[k]) + } + if !is_blankz(value, k) { + if !put_break(emitter) { + return false + } + } + } + if !write_break(emitter, value, &i) { + return false + } + emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + leading_spaces = is_blank(value, i) + } + if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + i += width(value[i]) + } else { + if !write(emitter, value, &i) { + return false + } + } + emitter.indention = false + breaks = false + } + } + return true +} diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/encode.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/encode.go new file mode 100644 index 00000000..84f84995 --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/encode.go @@ -0,0 +1,306 @@ +package yaml + +import ( + "encoding" + "fmt" + "reflect" + "regexp" + "sort" + "strconv" + "strings" + "time" +) + +type encoder struct { + emitter yaml_emitter_t + event yaml_event_t + out []byte + flow bool +} + +func newEncoder() (e *encoder) { + e = &encoder{} + e.must(yaml_emitter_initialize(&e.emitter)) + yaml_emitter_set_output_string(&e.emitter, &e.out) + yaml_emitter_set_unicode(&e.emitter, true) + e.must(yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)) + e.emit() + e.must(yaml_document_start_event_initialize(&e.event, nil, nil, true)) + e.emit() + return e +} + +func (e *encoder) finish() { + e.must(yaml_document_end_event_initialize(&e.event, true)) + e.emit() + e.emitter.open_ended = false + e.must(yaml_stream_end_event_initialize(&e.event)) + e.emit() +} + +func (e *encoder) destroy() { + yaml_emitter_delete(&e.emitter) +} + +func (e *encoder) emit() { + // This will internally delete the e.event value. + if !yaml_emitter_emit(&e.emitter, &e.event) && e.event.typ != yaml_DOCUMENT_END_EVENT && e.event.typ != yaml_STREAM_END_EVENT { + e.must(false) + } +} + +func (e *encoder) must(ok bool) { + if !ok { + msg := e.emitter.problem + if msg == "" { + msg = "unknown problem generating YAML content" + } + failf("%s", msg) + } +} + +func (e *encoder) marshal(tag string, in reflect.Value) { + if !in.IsValid() { + e.nilv() + return + } + iface := in.Interface() + if m, ok := iface.(Marshaler); ok { + v, err := m.MarshalYAML() + if err != nil { + fail(err) + } + if v == nil { + e.nilv() + return + } + in = reflect.ValueOf(v) + } else if m, ok := iface.(encoding.TextMarshaler); ok { + text, err := m.MarshalText() + if err != nil { + fail(err) + } + in = reflect.ValueOf(string(text)) + } + switch in.Kind() { + case reflect.Interface: + if in.IsNil() { + e.nilv() + } else { + e.marshal(tag, in.Elem()) + } + case reflect.Map: + e.mapv(tag, in) + case reflect.Ptr: + if in.IsNil() { + e.nilv() + } else { + e.marshal(tag, in.Elem()) + } + case reflect.Struct: + e.structv(tag, in) + case reflect.Slice: + if in.Type().Elem() == mapItemType { + e.itemsv(tag, in) + } else { + e.slicev(tag, in) + } + case reflect.String: + e.stringv(tag, in) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if in.Type() == durationType { + e.stringv(tag, reflect.ValueOf(iface.(time.Duration).String())) + } else { + e.intv(tag, in) + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + e.uintv(tag, in) + case reflect.Float32, reflect.Float64: + e.floatv(tag, in) + case reflect.Bool: + e.boolv(tag, in) + default: + panic("cannot marshal type: " + in.Type().String()) + } +} + +func (e *encoder) mapv(tag string, in reflect.Value) { + e.mappingv(tag, func() { + keys := keyList(in.MapKeys()) + sort.Sort(keys) + for _, k := range keys { + e.marshal("", k) + e.marshal("", in.MapIndex(k)) + } + }) +} + +func (e *encoder) itemsv(tag string, in reflect.Value) { + e.mappingv(tag, func() { + slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem) + for _, item := range slice { + e.marshal("", reflect.ValueOf(item.Key)) + e.marshal("", reflect.ValueOf(item.Value)) + } + }) +} + +func (e *encoder) structv(tag string, in reflect.Value) { + sinfo, err := getStructInfo(in.Type()) + if err != nil { + panic(err) + } + e.mappingv(tag, func() { + for _, info := range sinfo.FieldsList { + var value reflect.Value + if info.Inline == nil { + value = in.Field(info.Num) + } else { + value = in.FieldByIndex(info.Inline) + } + if info.OmitEmpty && isZero(value) { + continue + } + e.marshal("", reflect.ValueOf(info.Key)) + e.flow = info.Flow + e.marshal("", value) + } + if sinfo.InlineMap >= 0 { + m := in.Field(sinfo.InlineMap) + if m.Len() > 0 { + e.flow = false + keys := keyList(m.MapKeys()) + sort.Sort(keys) + for _, k := range keys { + if _, found := sinfo.FieldsMap[k.String()]; found { + panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", k.String())) + } + e.marshal("", k) + e.flow = false + e.marshal("", m.MapIndex(k)) + } + } + } + }) +} + +func (e *encoder) mappingv(tag string, f func()) { + implicit := tag == "" + style := yaml_BLOCK_MAPPING_STYLE + if e.flow { + e.flow = false + style = yaml_FLOW_MAPPING_STYLE + } + e.must(yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) + e.emit() + f() + e.must(yaml_mapping_end_event_initialize(&e.event)) + e.emit() +} + +func (e *encoder) slicev(tag string, in reflect.Value) { + implicit := tag == "" + style := yaml_BLOCK_SEQUENCE_STYLE + if e.flow { + e.flow = false + style = yaml_FLOW_SEQUENCE_STYLE + } + e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) + e.emit() + n := in.Len() + for i := 0; i < n; i++ { + e.marshal("", in.Index(i)) + } + e.must(yaml_sequence_end_event_initialize(&e.event)) + e.emit() +} + +// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. +// +// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported +// in YAML 1.2 and by this package, but these should be marshalled quoted for +// the time being for compatibility with other parsers. +func isBase60Float(s string) (result bool) { + // Fast path. + if s == "" { + return false + } + c := s[0] + if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { + return false + } + // Do the full match. + return base60float.MatchString(s) +} + +// From http://yaml.org/type/float.html, except the regular expression there +// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. +var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) + +func (e *encoder) stringv(tag string, in reflect.Value) { + var style yaml_scalar_style_t + s := in.String() + rtag, rs := resolve("", s) + if rtag == yaml_BINARY_TAG { + if tag == "" || tag == yaml_STR_TAG { + tag = rtag + s = rs.(string) + } else if tag == yaml_BINARY_TAG { + failf("explicitly tagged !!binary data must be base64-encoded") + } else { + failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) + } + } + if tag == "" && (rtag != yaml_STR_TAG || isBase60Float(s)) { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } else if strings.Contains(s, "\n") { + style = yaml_LITERAL_SCALAR_STYLE + } else { + style = yaml_PLAIN_SCALAR_STYLE + } + e.emitScalar(s, "", tag, style) +} + +func (e *encoder) boolv(tag string, in reflect.Value) { + var s string + if in.Bool() { + s = "true" + } else { + s = "false" + } + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) +} + +func (e *encoder) intv(tag string, in reflect.Value) { + s := strconv.FormatInt(in.Int(), 10) + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) +} + +func (e *encoder) uintv(tag string, in reflect.Value) { + s := strconv.FormatUint(in.Uint(), 10) + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) +} + +func (e *encoder) floatv(tag string, in reflect.Value) { + // FIXME: Handle 64 bits here. + s := strconv.FormatFloat(float64(in.Float()), 'g', -1, 32) + switch s { + case "+Inf": + s = ".inf" + case "-Inf": + s = "-.inf" + case "NaN": + s = ".nan" + } + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) +} + +func (e *encoder) nilv() { + e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE) +} + +func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) { + implicit := tag == "" + e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) + e.emit() +} diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/encode_test.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/encode_test.go new file mode 100644 index 00000000..51c90298 --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/encode_test.go @@ -0,0 +1,485 @@ +package yaml_test + +import ( + "fmt" + "math" + "strconv" + "strings" + "time" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/gopkg.in/yaml.v2" + . "gopkg.in/check.v1" + "net" + "os" +) + +var marshalIntTest = 123 + +var marshalTests = []struct { + value interface{} + data string +}{ + { + nil, + "null\n", + }, { + &struct{}{}, + "{}\n", + }, { + map[string]string{"v": "hi"}, + "v: hi\n", + }, { + map[string]interface{}{"v": "hi"}, + "v: hi\n", + }, { + map[string]string{"v": "true"}, + "v: \"true\"\n", + }, { + map[string]string{"v": "false"}, + "v: \"false\"\n", + }, { + map[string]interface{}{"v": true}, + "v: true\n", + }, { + map[string]interface{}{"v": false}, + "v: false\n", + }, { + map[string]interface{}{"v": 10}, + "v: 10\n", + }, { + map[string]interface{}{"v": -10}, + "v: -10\n", + }, { + map[string]uint{"v": 42}, + "v: 42\n", + }, { + map[string]interface{}{"v": int64(4294967296)}, + "v: 4294967296\n", + }, { + map[string]int64{"v": int64(4294967296)}, + "v: 4294967296\n", + }, { + map[string]uint64{"v": 4294967296}, + "v: 4294967296\n", + }, { + map[string]interface{}{"v": "10"}, + "v: \"10\"\n", + }, { + map[string]interface{}{"v": 0.1}, + "v: 0.1\n", + }, { + map[string]interface{}{"v": float64(0.1)}, + "v: 0.1\n", + }, { + map[string]interface{}{"v": -0.1}, + "v: -0.1\n", + }, { + map[string]interface{}{"v": math.Inf(+1)}, + "v: .inf\n", + }, { + map[string]interface{}{"v": math.Inf(-1)}, + "v: -.inf\n", + }, { + map[string]interface{}{"v": math.NaN()}, + "v: .nan\n", + }, { + map[string]interface{}{"v": nil}, + "v: null\n", + }, { + map[string]interface{}{"v": ""}, + "v: \"\"\n", + }, { + map[string][]string{"v": []string{"A", "B"}}, + "v:\n- A\n- B\n", + }, { + map[string][]string{"v": []string{"A", "B\nC"}}, + "v:\n- A\n- |-\n B\n C\n", + }, { + map[string][]interface{}{"v": []interface{}{"A", 1, map[string][]int{"B": []int{2, 3}}}}, + "v:\n- A\n- 1\n- B:\n - 2\n - 3\n", + }, { + map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}}, + "a:\n b: c\n", + }, { + map[string]interface{}{"a": "-"}, + "a: '-'\n", + }, + + // Simple values. + { + &marshalIntTest, + "123\n", + }, + + // Structures + { + &struct{ Hello string }{"world"}, + "hello: world\n", + }, { + &struct { + A struct { + B string + } + }{struct{ B string }{"c"}}, + "a:\n b: c\n", + }, { + &struct { + A *struct { + B string + } + }{&struct{ B string }{"c"}}, + "a:\n b: c\n", + }, { + &struct { + A *struct { + B string + } + }{}, + "a: null\n", + }, { + &struct{ A int }{1}, + "a: 1\n", + }, { + &struct{ A []int }{[]int{1, 2}}, + "a:\n- 1\n- 2\n", + }, { + &struct { + B int "a" + }{1}, + "a: 1\n", + }, { + &struct{ A bool }{true}, + "a: true\n", + }, + + // Conditional flag + { + &struct { + A int "a,omitempty" + B int "b,omitempty" + }{1, 0}, + "a: 1\n", + }, { + &struct { + A int "a,omitempty" + B int "b,omitempty" + }{0, 0}, + "{}\n", + }, { + &struct { + A *struct{ X, y int } "a,omitempty,flow" + }{&struct{ X, y int }{1, 2}}, + "a: {x: 1}\n", + }, { + &struct { + A *struct{ X, y int } "a,omitempty,flow" + }{nil}, + "{}\n", + }, { + &struct { + A *struct{ X, y int } "a,omitempty,flow" + }{&struct{ X, y int }{}}, + "a: {x: 0}\n", + }, { + &struct { + A struct{ X, y int } "a,omitempty,flow" + }{struct{ X, y int }{1, 2}}, + "a: {x: 1}\n", + }, { + &struct { + A struct{ X, y int } "a,omitempty,flow" + }{struct{ X, y int }{0, 1}}, + "{}\n", + }, + + // Flow flag + { + &struct { + A []int "a,flow" + }{[]int{1, 2}}, + "a: [1, 2]\n", + }, { + &struct { + A map[string]string "a,flow" + }{map[string]string{"b": "c", "d": "e"}}, + "a: {b: c, d: e}\n", + }, { + &struct { + A struct { + B, D string + } "a,flow" + }{struct{ B, D string }{"c", "e"}}, + "a: {b: c, d: e}\n", + }, + + // Unexported field + { + &struct { + u int + A int + }{0, 1}, + "a: 1\n", + }, + + // Ignored field + { + &struct { + A int + B int "-" + }{1, 2}, + "a: 1\n", + }, + + // Struct inlining + { + &struct { + A int + C inlineB `yaml:",inline"` + }{1, inlineB{2, inlineC{3}}}, + "a: 1\nb: 2\nc: 3\n", + }, + + // Map inlining + { + &struct { + A int + C map[string]int `yaml:",inline"` + }{1, map[string]int{"b": 2, "c": 3}}, + "a: 1\nb: 2\nc: 3\n", + }, + + // Duration + { + map[string]time.Duration{"a": 3 * time.Second}, + "a: 3s\n", + }, + + // Issue #24: bug in map merging logic. + { + map[string]string{"a": ""}, + "a: \n", + }, + + // Issue #34: marshal unsupported base 60 floats quoted for compatibility + // with old YAML 1.1 parsers. + { + map[string]string{"a": "1:1"}, + "a: \"1:1\"\n", + }, + + // Binary data. + { + map[string]string{"a": "\x00"}, + "a: \"\\0\"\n", + }, { + map[string]string{"a": "\x80\x81\x82"}, + "a: !!binary gIGC\n", + }, { + map[string]string{"a": strings.Repeat("\x90", 54)}, + "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n", + }, + + // Ordered maps. + { + &yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}}, + "b: 2\na: 1\nd: 4\nc: 3\nsub:\n e: 5\n", + }, + + // Encode unicode as utf-8 rather than in escaped form. + { + map[string]string{"a": "你好"}, + "a: 你好\n", + }, + + // Support encoding.TextMarshaler. + { + map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)}, + "a: 1.2.3.4\n", + }, + { + map[string]time.Time{"a": time.Unix(1424801979, 0)}, + "a: 2015-02-24T18:19:39Z\n", + }, + + // Ensure strings containing ": " are quoted (reported as PR #43, but not reproducible). + { + map[string]string{"a": "b: c"}, + "a: 'b: c'\n", + }, +} + +func (s *S) TestMarshal(c *C) { + defer os.Setenv("TZ", os.Getenv("TZ")) + os.Setenv("TZ", "UTC") + for _, item := range marshalTests { + data, err := yaml.Marshal(item.value) + c.Assert(err, IsNil) + c.Assert(string(data), Equals, item.data) + } +} + +var marshalErrorTests = []struct { + value interface{} + error string + panic string +}{{ + value: &struct { + B int + inlineB ",inline" + }{1, inlineB{2, inlineC{3}}}, + panic: `Duplicated key 'b' in struct struct \{ B int; .*`, +}, { + value: &struct { + A int + B map[string]int ",inline" + }{1, map[string]int{"a": 2}}, + panic: `Can't have key "a" in inlined map; conflicts with struct field`, +}} + +func (s *S) TestMarshalErrors(c *C) { + for _, item := range marshalErrorTests { + if item.panic != "" { + c.Assert(func() { yaml.Marshal(item.value) }, PanicMatches, item.panic) + } else { + _, err := yaml.Marshal(item.value) + c.Assert(err, ErrorMatches, item.error) + } + } +} + +func (s *S) TestMarshalTypeCache(c *C) { + var data []byte + var err error + func() { + type T struct{ A int } + data, err = yaml.Marshal(&T{}) + c.Assert(err, IsNil) + }() + func() { + type T struct{ B int } + data, err = yaml.Marshal(&T{}) + c.Assert(err, IsNil) + }() + c.Assert(string(data), Equals, "b: 0\n") +} + +var marshalerTests = []struct { + data string + value interface{} +}{ + {"_:\n hi: there\n", map[interface{}]interface{}{"hi": "there"}}, + {"_:\n- 1\n- A\n", []interface{}{1, "A"}}, + {"_: 10\n", 10}, + {"_: null\n", nil}, + {"_: BAR!\n", "BAR!"}, +} + +type marshalerType struct { + value interface{} +} + +func (o marshalerType) MarshalText() ([]byte, error) { + panic("MarshalText called on type with MarshalYAML") +} + +func (o marshalerType) MarshalYAML() (interface{}, error) { + return o.value, nil +} + +type marshalerValue struct { + Field marshalerType "_" +} + +func (s *S) TestMarshaler(c *C) { + for _, item := range marshalerTests { + obj := &marshalerValue{} + obj.Field.value = item.value + data, err := yaml.Marshal(obj) + c.Assert(err, IsNil) + c.Assert(string(data), Equals, string(item.data)) + } +} + +func (s *S) TestMarshalerWholeDocument(c *C) { + obj := &marshalerType{} + obj.value = map[string]string{"hello": "world!"} + data, err := yaml.Marshal(obj) + c.Assert(err, IsNil) + c.Assert(string(data), Equals, "hello: world!\n") +} + +type failingMarshaler struct{} + +func (ft *failingMarshaler) MarshalYAML() (interface{}, error) { + return nil, failingErr +} + +func (s *S) TestMarshalerError(c *C) { + _, err := yaml.Marshal(&failingMarshaler{}) + c.Assert(err, Equals, failingErr) +} + +func (s *S) TestSortedOutput(c *C) { + order := []interface{}{ + false, + true, + 1, + uint(1), + 1.0, + 1.1, + 1.2, + 2, + uint(2), + 2.0, + 2.1, + "", + ".1", + ".2", + ".a", + "1", + "2", + "a!10", + "a/2", + "a/10", + "a~10", + "ab/1", + "b/1", + "b/01", + "b/2", + "b/02", + "b/3", + "b/03", + "b1", + "b01", + "b3", + "c2.10", + "c10.2", + "d1", + "d12", + "d12a", + } + m := make(map[interface{}]int) + for _, k := range order { + m[k] = 1 + } + data, err := yaml.Marshal(m) + c.Assert(err, IsNil) + out := "\n" + string(data) + last := 0 + for i, k := range order { + repr := fmt.Sprint(k) + if s, ok := k.(string); ok { + if _, err = strconv.ParseFloat(repr, 32); s == "" || err == nil { + repr = `"` + repr + `"` + } + } + index := strings.Index(out, "\n"+repr+":") + if index == -1 { + c.Fatalf("%#v is not in the output: %#v", k, out) + } + if index < last { + c.Fatalf("%#v was generated before %#v: %q", k, order[i-1], out) + } + last = index + } +} diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/parserc.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/parserc.go new file mode 100644 index 00000000..0a7037ad --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/parserc.go @@ -0,0 +1,1096 @@ +package yaml + +import ( + "bytes" +) + +// The parser implements the following grammar: +// +// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END +// implicit_document ::= block_node DOCUMENT-END* +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// block_node_or_indentless_sequence ::= +// ALIAS +// | properties (block_content | indentless_block_sequence)? +// | block_content +// | indentless_block_sequence +// block_node ::= ALIAS +// | properties block_content? +// | block_content +// flow_node ::= ALIAS +// | properties flow_content? +// | flow_content +// properties ::= TAG ANCHOR? | ANCHOR TAG? +// block_content ::= block_collection | flow_collection | SCALAR +// flow_content ::= flow_collection | SCALAR +// block_collection ::= block_sequence | block_mapping +// flow_collection ::= flow_sequence | flow_mapping +// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END +// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ +// block_mapping ::= BLOCK-MAPPING_START +// ((KEY block_node_or_indentless_sequence?)? +// (VALUE block_node_or_indentless_sequence?)?)* +// BLOCK-END +// flow_sequence ::= FLOW-SEQUENCE-START +// (flow_sequence_entry FLOW-ENTRY)* +// flow_sequence_entry? +// FLOW-SEQUENCE-END +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// flow_mapping ::= FLOW-MAPPING-START +// (flow_mapping_entry FLOW-ENTRY)* +// flow_mapping_entry? +// FLOW-MAPPING-END +// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? + +// Peek the next token in the token queue. +func peek_token(parser *yaml_parser_t) *yaml_token_t { + if parser.token_available || yaml_parser_fetch_more_tokens(parser) { + return &parser.tokens[parser.tokens_head] + } + return nil +} + +// Remove the next token from the queue (must be called after peek_token). +func skip_token(parser *yaml_parser_t) { + parser.token_available = false + parser.tokens_parsed++ + parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN + parser.tokens_head++ +} + +// Get the next event. +func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool { + // Erase the event object. + *event = yaml_event_t{} + + // No events after the end of the stream or error. + if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE { + return true + } + + // Generate the next event. + return yaml_parser_state_machine(parser, event) +} + +// Set parser error. +func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool { + parser.error = yaml_PARSER_ERROR + parser.problem = problem + parser.problem_mark = problem_mark + return false +} + +func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool { + parser.error = yaml_PARSER_ERROR + parser.context = context + parser.context_mark = context_mark + parser.problem = problem + parser.problem_mark = problem_mark + return false +} + +// State dispatcher. +func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool { + //trace("yaml_parser_state_machine", "state:", parser.state.String()) + + switch parser.state { + case yaml_PARSE_STREAM_START_STATE: + return yaml_parser_parse_stream_start(parser, event) + + case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: + return yaml_parser_parse_document_start(parser, event, true) + + case yaml_PARSE_DOCUMENT_START_STATE: + return yaml_parser_parse_document_start(parser, event, false) + + case yaml_PARSE_DOCUMENT_CONTENT_STATE: + return yaml_parser_parse_document_content(parser, event) + + case yaml_PARSE_DOCUMENT_END_STATE: + return yaml_parser_parse_document_end(parser, event) + + case yaml_PARSE_BLOCK_NODE_STATE: + return yaml_parser_parse_node(parser, event, true, false) + + case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: + return yaml_parser_parse_node(parser, event, true, true) + + case yaml_PARSE_FLOW_NODE_STATE: + return yaml_parser_parse_node(parser, event, false, false) + + case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: + return yaml_parser_parse_block_sequence_entry(parser, event, true) + + case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_block_sequence_entry(parser, event, false) + + case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_indentless_sequence_entry(parser, event) + + case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: + return yaml_parser_parse_block_mapping_key(parser, event, true) + + case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: + return yaml_parser_parse_block_mapping_key(parser, event, false) + + case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: + return yaml_parser_parse_block_mapping_value(parser, event) + + case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: + return yaml_parser_parse_flow_sequence_entry(parser, event, true) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_flow_sequence_entry(parser, event, false) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event) + + case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: + return yaml_parser_parse_flow_mapping_key(parser, event, true) + + case yaml_PARSE_FLOW_MAPPING_KEY_STATE: + return yaml_parser_parse_flow_mapping_key(parser, event, false) + + case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: + return yaml_parser_parse_flow_mapping_value(parser, event, false) + + case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: + return yaml_parser_parse_flow_mapping_value(parser, event, true) + + default: + panic("invalid parser state") + } + return false +} + +// Parse the production: +// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END +// ************ +func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_STREAM_START_TOKEN { + return yaml_parser_set_parser_error(parser, "did not find expected ", token.start_mark) + } + parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE + *event = yaml_event_t{ + typ: yaml_STREAM_START_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + encoding: token.encoding, + } + skip_token(parser) + return true +} + +// Parse the productions: +// implicit_document ::= block_node DOCUMENT-END* +// * +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// ************************* +func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool { + + token := peek_token(parser) + if token == nil { + return false + } + + // Parse extra document end indicators. + if !implicit { + for token.typ == yaml_DOCUMENT_END_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + } + + if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN && + token.typ != yaml_TAG_DIRECTIVE_TOKEN && + token.typ != yaml_DOCUMENT_START_TOKEN && + token.typ != yaml_STREAM_END_TOKEN { + // Parse an implicit document. + if !yaml_parser_process_directives(parser, nil, nil) { + return false + } + parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) + parser.state = yaml_PARSE_BLOCK_NODE_STATE + + *event = yaml_event_t{ + typ: yaml_DOCUMENT_START_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + + } else if token.typ != yaml_STREAM_END_TOKEN { + // Parse an explicit document. + var version_directive *yaml_version_directive_t + var tag_directives []yaml_tag_directive_t + start_mark := token.start_mark + if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) { + return false + } + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_DOCUMENT_START_TOKEN { + yaml_parser_set_parser_error(parser, + "did not find expected ", token.start_mark) + return false + } + parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) + parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE + end_mark := token.end_mark + + *event = yaml_event_t{ + typ: yaml_DOCUMENT_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + version_directive: version_directive, + tag_directives: tag_directives, + implicit: false, + } + skip_token(parser) + + } else { + // Parse the stream end. + parser.state = yaml_PARSE_END_STATE + *event = yaml_event_t{ + typ: yaml_STREAM_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + skip_token(parser) + } + + return true +} + +// Parse the productions: +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// *********** +// +func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_VERSION_DIRECTIVE_TOKEN || + token.typ == yaml_TAG_DIRECTIVE_TOKEN || + token.typ == yaml_DOCUMENT_START_TOKEN || + token.typ == yaml_DOCUMENT_END_TOKEN || + token.typ == yaml_STREAM_END_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + return yaml_parser_process_empty_scalar(parser, event, + token.start_mark) + } + return yaml_parser_parse_node(parser, event, true, false) +} + +// Parse the productions: +// implicit_document ::= block_node DOCUMENT-END* +// ************* +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// +func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + + start_mark := token.start_mark + end_mark := token.start_mark + + implicit := true + if token.typ == yaml_DOCUMENT_END_TOKEN { + end_mark = token.end_mark + skip_token(parser) + implicit = false + } + + parser.tag_directives = parser.tag_directives[:0] + + parser.state = yaml_PARSE_DOCUMENT_START_STATE + *event = yaml_event_t{ + typ: yaml_DOCUMENT_END_EVENT, + start_mark: start_mark, + end_mark: end_mark, + implicit: implicit, + } + return true +} + +// Parse the productions: +// block_node_or_indentless_sequence ::= +// ALIAS +// ***** +// | properties (block_content | indentless_block_sequence)? +// ********** * +// | block_content | indentless_block_sequence +// * +// block_node ::= ALIAS +// ***** +// | properties block_content? +// ********** * +// | block_content +// * +// flow_node ::= ALIAS +// ***** +// | properties flow_content? +// ********** * +// | flow_content +// * +// properties ::= TAG ANCHOR? | ANCHOR TAG? +// ************************* +// block_content ::= block_collection | flow_collection | SCALAR +// ****** +// flow_content ::= flow_collection | SCALAR +// ****** +func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool { + //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)() + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_ALIAS_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + *event = yaml_event_t{ + typ: yaml_ALIAS_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + anchor: token.value, + } + skip_token(parser) + return true + } + + start_mark := token.start_mark + end_mark := token.start_mark + + var tag_token bool + var tag_handle, tag_suffix, anchor []byte + var tag_mark yaml_mark_t + if token.typ == yaml_ANCHOR_TOKEN { + anchor = token.value + start_mark = token.start_mark + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_TAG_TOKEN { + tag_token = true + tag_handle = token.value + tag_suffix = token.suffix + tag_mark = token.start_mark + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + } else if token.typ == yaml_TAG_TOKEN { + tag_token = true + tag_handle = token.value + tag_suffix = token.suffix + start_mark = token.start_mark + tag_mark = token.start_mark + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_ANCHOR_TOKEN { + anchor = token.value + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + } + + var tag []byte + if tag_token { + if len(tag_handle) == 0 { + tag = tag_suffix + tag_suffix = nil + } else { + for i := range parser.tag_directives { + if bytes.Equal(parser.tag_directives[i].handle, tag_handle) { + tag = append([]byte(nil), parser.tag_directives[i].prefix...) + tag = append(tag, tag_suffix...) + break + } + } + if len(tag) == 0 { + yaml_parser_set_parser_error_context(parser, + "while parsing a node", start_mark, + "found undefined tag handle", tag_mark) + return false + } + } + } + + implicit := len(tag) == 0 + if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), + } + return true + } + if token.typ == yaml_SCALAR_TOKEN { + var plain_implicit, quoted_implicit bool + end_mark = token.end_mark + if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') { + plain_implicit = true + } else if len(tag) == 0 { + quoted_implicit = true + } + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + value: token.value, + implicit: plain_implicit, + quoted_implicit: quoted_implicit, + style: yaml_style_t(token.style), + } + skip_token(parser) + return true + } + if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN { + // [Go] Some of the events below can be merged as they differ only on style. + end_mark = token.end_mark + parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE), + } + return true + } + if token.typ == yaml_FLOW_MAPPING_START_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), + } + return true + } + if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), + } + return true + } + if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE), + } + return true + } + if len(anchor) > 0 || len(tag) > 0 { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + quoted_implicit: false, + style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), + } + return true + } + + context := "while parsing a flow node" + if block { + context = "while parsing a block node" + } + yaml_parser_set_parser_error_context(parser, context, start_mark, + "did not find expected node content", token.start_mark) + return false +} + +// Parse the productions: +// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END +// ******************** *********** * ********* +// +func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_BLOCK_ENTRY_TOKEN { + mark := token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE) + return yaml_parser_parse_node(parser, event, true, false) + } else { + parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + } + if token.typ == yaml_BLOCK_END_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + + skip_token(parser) + return true + } + + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a block collection", context_mark, + "did not find expected '-' indicator", token.start_mark) +} + +// Parse the productions: +// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ +// *********** * +func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_BLOCK_ENTRY_TOKEN { + mark := token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_BLOCK_ENTRY_TOKEN && + token.typ != yaml_KEY_TOKEN && + token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE) + return yaml_parser_parse_node(parser, event, true, false) + } + parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + start_mark: token.start_mark, + end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark? + } + return true +} + +// Parse the productions: +// block_mapping ::= BLOCK-MAPPING_START +// ******************* +// ((KEY block_node_or_indentless_sequence?)? +// *** * +// (VALUE block_node_or_indentless_sequence?)?)* +// +// BLOCK-END +// ********* +// +func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_KEY_TOKEN { + mark := token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_KEY_TOKEN && + token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE) + return yaml_parser_parse_node(parser, event, true, true) + } else { + parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + } else if token.typ == yaml_BLOCK_END_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + skip_token(parser) + return true + } + + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a block mapping", context_mark, + "did not find expected key", token.start_mark) +} + +// Parse the productions: +// block_mapping ::= BLOCK-MAPPING_START +// +// ((KEY block_node_or_indentless_sequence?)? +// +// (VALUE block_node_or_indentless_sequence?)?)* +// ***** * +// BLOCK-END +// +// +func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_VALUE_TOKEN { + mark := token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_KEY_TOKEN && + token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE) + return yaml_parser_parse_node(parser, event, true, true) + } + parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) +} + +// Parse the productions: +// flow_sequence ::= FLOW-SEQUENCE-START +// ******************* +// (flow_sequence_entry FLOW-ENTRY)* +// * ********** +// flow_sequence_entry? +// * +// FLOW-SEQUENCE-END +// ***************** +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// * +// +func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + if !first { + if token.typ == yaml_FLOW_ENTRY_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } else { + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a flow sequence", context_mark, + "did not find expected ',' or ']'", token.start_mark) + } + } + + if token.typ == yaml_KEY_TOKEN { + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + implicit: true, + style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), + } + skip_token(parser) + return true + } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + + skip_token(parser) + return true +} + +// +// Parse the productions: +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// *** * +// +func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_FLOW_ENTRY_TOKEN && + token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + mark := token.end_mark + skip_token(parser) + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) +} + +// Parse the productions: +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// ***** * +// +func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_VALUE_TOKEN { + skip_token(parser) + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) +} + +// Parse the productions: +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// * +// +func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + start_mark: token.start_mark, + end_mark: token.start_mark, // [Go] Shouldn't this be end_mark? + } + return true +} + +// Parse the productions: +// flow_mapping ::= FLOW-MAPPING-START +// ****************** +// (flow_mapping_entry FLOW-ENTRY)* +// * ********** +// flow_mapping_entry? +// ****************** +// FLOW-MAPPING-END +// **************** +// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// * *** * +// +func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ != yaml_FLOW_MAPPING_END_TOKEN { + if !first { + if token.typ == yaml_FLOW_ENTRY_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } else { + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a flow mapping", context_mark, + "did not find expected ',' or '}'", token.start_mark) + } + } + + if token.typ == yaml_KEY_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_FLOW_ENTRY_TOKEN && + token.typ != yaml_FLOW_MAPPING_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } else { + parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) + } + } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + skip_token(parser) + return true +} + +// Parse the productions: +// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// * ***** * +// +func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool { + token := peek_token(parser) + if token == nil { + return false + } + if empty { + parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) + } + if token.typ == yaml_VALUE_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) +} + +// Generate an empty scalar event. +func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool { + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + start_mark: mark, + end_mark: mark, + value: nil, // Empty + implicit: true, + style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), + } + return true +} + +var default_tag_directives = []yaml_tag_directive_t{ + {[]byte("!"), []byte("!")}, + {[]byte("!!"), []byte("tag:yaml.org,2002:")}, +} + +// Parse directives. +func yaml_parser_process_directives(parser *yaml_parser_t, + version_directive_ref **yaml_version_directive_t, + tag_directives_ref *[]yaml_tag_directive_t) bool { + + var version_directive *yaml_version_directive_t + var tag_directives []yaml_tag_directive_t + + token := peek_token(parser) + if token == nil { + return false + } + + for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN { + if token.typ == yaml_VERSION_DIRECTIVE_TOKEN { + if version_directive != nil { + yaml_parser_set_parser_error(parser, + "found duplicate %YAML directive", token.start_mark) + return false + } + if token.major != 1 || token.minor != 1 { + yaml_parser_set_parser_error(parser, + "found incompatible YAML document", token.start_mark) + return false + } + version_directive = &yaml_version_directive_t{ + major: token.major, + minor: token.minor, + } + } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN { + value := yaml_tag_directive_t{ + handle: token.value, + prefix: token.prefix, + } + if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) { + return false + } + tag_directives = append(tag_directives, value) + } + + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + + for i := range default_tag_directives { + if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) { + return false + } + } + + if version_directive_ref != nil { + *version_directive_ref = version_directive + } + if tag_directives_ref != nil { + *tag_directives_ref = tag_directives + } + return true +} + +// Append a tag directive to the directives stack. +func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool { + for i := range parser.tag_directives { + if bytes.Equal(value.handle, parser.tag_directives[i].handle) { + if allow_duplicates { + return true + } + return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark) + } + } + + // [Go] I suspect the copy is unnecessary. This was likely done + // because there was no way to track ownership of the data. + value_copy := yaml_tag_directive_t{ + handle: make([]byte, len(value.handle)), + prefix: make([]byte, len(value.prefix)), + } + copy(value_copy.handle, value.handle) + copy(value_copy.prefix, value.prefix) + parser.tag_directives = append(parser.tag_directives, value_copy) + return true +} diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/readerc.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/readerc.go new file mode 100644 index 00000000..d5fb0972 --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/readerc.go @@ -0,0 +1,391 @@ +package yaml + +import ( + "io" +) + +// Set the reader error and return 0. +func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool { + parser.error = yaml_READER_ERROR + parser.problem = problem + parser.problem_offset = offset + parser.problem_value = value + return false +} + +// Byte order marks. +const ( + bom_UTF8 = "\xef\xbb\xbf" + bom_UTF16LE = "\xff\xfe" + bom_UTF16BE = "\xfe\xff" +) + +// Determine the input stream encoding by checking the BOM symbol. If no BOM is +// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure. +func yaml_parser_determine_encoding(parser *yaml_parser_t) bool { + // Ensure that we had enough bytes in the raw buffer. + for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 { + if !yaml_parser_update_raw_buffer(parser) { + return false + } + } + + // Determine the encoding. + buf := parser.raw_buffer + pos := parser.raw_buffer_pos + avail := len(buf) - pos + if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] { + parser.encoding = yaml_UTF16LE_ENCODING + parser.raw_buffer_pos += 2 + parser.offset += 2 + } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] { + parser.encoding = yaml_UTF16BE_ENCODING + parser.raw_buffer_pos += 2 + parser.offset += 2 + } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] { + parser.encoding = yaml_UTF8_ENCODING + parser.raw_buffer_pos += 3 + parser.offset += 3 + } else { + parser.encoding = yaml_UTF8_ENCODING + } + return true +} + +// Update the raw buffer. +func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool { + size_read := 0 + + // Return if the raw buffer is full. + if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) { + return true + } + + // Return on EOF. + if parser.eof { + return true + } + + // Move the remaining bytes in the raw buffer to the beginning. + if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) { + copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:]) + } + parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos] + parser.raw_buffer_pos = 0 + + // Call the read handler to fill the buffer. + size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)]) + parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read] + if err == io.EOF { + parser.eof = true + } else if err != nil { + return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1) + } + return true +} + +// Ensure that the buffer contains at least `length` characters. +// Return true on success, false on failure. +// +// The length is supposed to be significantly less that the buffer size. +func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { + if parser.read_handler == nil { + panic("read handler must be set") + } + + // If the EOF flag is set and the raw buffer is empty, do nothing. + if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { + return true + } + + // Return if the buffer contains enough characters. + if parser.unread >= length { + return true + } + + // Determine the input encoding if it is not known yet. + if parser.encoding == yaml_ANY_ENCODING { + if !yaml_parser_determine_encoding(parser) { + return false + } + } + + // Move the unread characters to the beginning of the buffer. + buffer_len := len(parser.buffer) + if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len { + copy(parser.buffer, parser.buffer[parser.buffer_pos:]) + buffer_len -= parser.buffer_pos + parser.buffer_pos = 0 + } else if parser.buffer_pos == buffer_len { + buffer_len = 0 + parser.buffer_pos = 0 + } + + // Open the whole buffer for writing, and cut it before returning. + parser.buffer = parser.buffer[:cap(parser.buffer)] + + // Fill the buffer until it has enough characters. + first := true + for parser.unread < length { + + // Fill the raw buffer if necessary. + if !first || parser.raw_buffer_pos == len(parser.raw_buffer) { + if !yaml_parser_update_raw_buffer(parser) { + parser.buffer = parser.buffer[:buffer_len] + return false + } + } + first = false + + // Decode the raw buffer. + inner: + for parser.raw_buffer_pos != len(parser.raw_buffer) { + var value rune + var width int + + raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos + + // Decode the next character. + switch parser.encoding { + case yaml_UTF8_ENCODING: + // Decode a UTF-8 character. Check RFC 3629 + // (http://www.ietf.org/rfc/rfc3629.txt) for more details. + // + // The following table (taken from the RFC) is used for + // decoding. + // + // Char. number range | UTF-8 octet sequence + // (hexadecimal) | (binary) + // --------------------+------------------------------------ + // 0000 0000-0000 007F | 0xxxxxxx + // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + // + // Additionally, the characters in the range 0xD800-0xDFFF + // are prohibited as they are reserved for use with UTF-16 + // surrogate pairs. + + // Determine the length of the UTF-8 sequence. + octet := parser.raw_buffer[parser.raw_buffer_pos] + switch { + case octet&0x80 == 0x00: + width = 1 + case octet&0xE0 == 0xC0: + width = 2 + case octet&0xF0 == 0xE0: + width = 3 + case octet&0xF8 == 0xF0: + width = 4 + default: + // The leading octet is invalid. + return yaml_parser_set_reader_error(parser, + "invalid leading UTF-8 octet", + parser.offset, int(octet)) + } + + // Check if the raw buffer contains an incomplete character. + if width > raw_unread { + if parser.eof { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-8 octet sequence", + parser.offset, -1) + } + break inner + } + + // Decode the leading octet. + switch { + case octet&0x80 == 0x00: + value = rune(octet & 0x7F) + case octet&0xE0 == 0xC0: + value = rune(octet & 0x1F) + case octet&0xF0 == 0xE0: + value = rune(octet & 0x0F) + case octet&0xF8 == 0xF0: + value = rune(octet & 0x07) + default: + value = 0 + } + + // Check and decode the trailing octets. + for k := 1; k < width; k++ { + octet = parser.raw_buffer[parser.raw_buffer_pos+k] + + // Check if the octet is valid. + if (octet & 0xC0) != 0x80 { + return yaml_parser_set_reader_error(parser, + "invalid trailing UTF-8 octet", + parser.offset+k, int(octet)) + } + + // Decode the octet. + value = (value << 6) + rune(octet&0x3F) + } + + // Check the length of the sequence against the value. + switch { + case width == 1: + case width == 2 && value >= 0x80: + case width == 3 && value >= 0x800: + case width == 4 && value >= 0x10000: + default: + return yaml_parser_set_reader_error(parser, + "invalid length of a UTF-8 sequence", + parser.offset, -1) + } + + // Check the range of the value. + if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF { + return yaml_parser_set_reader_error(parser, + "invalid Unicode character", + parser.offset, int(value)) + } + + case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING: + var low, high int + if parser.encoding == yaml_UTF16LE_ENCODING { + low, high = 0, 1 + } else { + high, low = 1, 0 + } + + // The UTF-16 encoding is not as simple as one might + // naively think. Check RFC 2781 + // (http://www.ietf.org/rfc/rfc2781.txt). + // + // Normally, two subsequent bytes describe a Unicode + // character. However a special technique (called a + // surrogate pair) is used for specifying character + // values larger than 0xFFFF. + // + // A surrogate pair consists of two pseudo-characters: + // high surrogate area (0xD800-0xDBFF) + // low surrogate area (0xDC00-0xDFFF) + // + // The following formulas are used for decoding + // and encoding characters using surrogate pairs: + // + // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF) + // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF) + // W1 = 110110yyyyyyyyyy + // W2 = 110111xxxxxxxxxx + // + // where U is the character value, W1 is the high surrogate + // area, W2 is the low surrogate area. + + // Check for incomplete UTF-16 character. + if raw_unread < 2 { + if parser.eof { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-16 character", + parser.offset, -1) + } + break inner + } + + // Get the character. + value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) + + (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8) + + // Check for unexpected low surrogate area. + if value&0xFC00 == 0xDC00 { + return yaml_parser_set_reader_error(parser, + "unexpected low surrogate area", + parser.offset, int(value)) + } + + // Check for a high surrogate area. + if value&0xFC00 == 0xD800 { + width = 4 + + // Check for incomplete surrogate pair. + if raw_unread < 4 { + if parser.eof { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-16 surrogate pair", + parser.offset, -1) + } + break inner + } + + // Get the next character. + value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) + + (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8) + + // Check for a low surrogate area. + if value2&0xFC00 != 0xDC00 { + return yaml_parser_set_reader_error(parser, + "expected low surrogate area", + parser.offset+2, int(value2)) + } + + // Generate the value of the surrogate pair. + value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF) + } else { + width = 2 + } + + default: + panic("impossible") + } + + // Check if the character is in the allowed range: + // #x9 | #xA | #xD | [#x20-#x7E] (8 bit) + // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit) + // | [#x10000-#x10FFFF] (32 bit) + switch { + case value == 0x09: + case value == 0x0A: + case value == 0x0D: + case value >= 0x20 && value <= 0x7E: + case value == 0x85: + case value >= 0xA0 && value <= 0xD7FF: + case value >= 0xE000 && value <= 0xFFFD: + case value >= 0x10000 && value <= 0x10FFFF: + default: + return yaml_parser_set_reader_error(parser, + "control characters are not allowed", + parser.offset, int(value)) + } + + // Move the raw pointers. + parser.raw_buffer_pos += width + parser.offset += width + + // Finally put the character into the buffer. + if value <= 0x7F { + // 0000 0000-0000 007F . 0xxxxxxx + parser.buffer[buffer_len+0] = byte(value) + } else if value <= 0x7FF { + // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx + parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) + parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) + } else if value <= 0xFFFF { + // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx + parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) + parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) + parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) + } else { + // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) + parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) + parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) + parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) + } + buffer_len += width + + parser.unread++ + } + + // On EOF, put NUL into the buffer and return. + if parser.eof { + parser.buffer[buffer_len] = 0 + buffer_len++ + parser.unread++ + break + } + } + parser.buffer = parser.buffer[:buffer_len] + return true +} diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/resolve.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/resolve.go new file mode 100644 index 00000000..93a86327 --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/resolve.go @@ -0,0 +1,203 @@ +package yaml + +import ( + "encoding/base64" + "math" + "strconv" + "strings" + "unicode/utf8" +) + +type resolveMapItem struct { + value interface{} + tag string +} + +var resolveTable = make([]byte, 256) +var resolveMap = make(map[string]resolveMapItem) + +func init() { + t := resolveTable + t[int('+')] = 'S' // Sign + t[int('-')] = 'S' + for _, c := range "0123456789" { + t[int(c)] = 'D' // Digit + } + for _, c := range "yYnNtTfFoO~" { + t[int(c)] = 'M' // In map + } + t[int('.')] = '.' // Float (potentially in map) + + var resolveMapList = []struct { + v interface{} + tag string + l []string + }{ + {true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}}, + {true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}}, + {true, yaml_BOOL_TAG, []string{"on", "On", "ON"}}, + {false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}}, + {false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}}, + {false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}}, + {nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}}, + {math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}}, + {math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}}, + {math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}}, + {math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}}, + {"<<", yaml_MERGE_TAG, []string{"<<"}}, + } + + m := resolveMap + for _, item := range resolveMapList { + for _, s := range item.l { + m[s] = resolveMapItem{item.v, item.tag} + } + } +} + +const longTagPrefix = "tag:yaml.org,2002:" + +func shortTag(tag string) string { + // TODO This can easily be made faster and produce less garbage. + if strings.HasPrefix(tag, longTagPrefix) { + return "!!" + tag[len(longTagPrefix):] + } + return tag +} + +func longTag(tag string) string { + if strings.HasPrefix(tag, "!!") { + return longTagPrefix + tag[2:] + } + return tag +} + +func resolvableTag(tag string) bool { + switch tag { + case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG: + return true + } + return false +} + +func resolve(tag string, in string) (rtag string, out interface{}) { + if !resolvableTag(tag) { + return tag, in + } + + defer func() { + switch tag { + case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG: + return + } + failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) + }() + + // Any data is accepted as a !!str or !!binary. + // Otherwise, the prefix is enough of a hint about what it might be. + hint := byte('N') + if in != "" { + hint = resolveTable[in[0]] + } + if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG { + // Handle things we can lookup in a map. + if item, ok := resolveMap[in]; ok { + return item.tag, item.value + } + + // Base 60 floats are a bad idea, were dropped in YAML 1.2, and + // are purposefully unsupported here. They're still quoted on + // the way out for compatibility with other parser, though. + + switch hint { + case 'M': + // We've already checked the map above. + + case '.': + // Not in the map, so maybe a normal float. + floatv, err := strconv.ParseFloat(in, 64) + if err == nil { + return yaml_FLOAT_TAG, floatv + } + + case 'D', 'S': + // Int, float, or timestamp. + plain := strings.Replace(in, "_", "", -1) + intv, err := strconv.ParseInt(plain, 0, 64) + if err == nil { + if intv == int64(int(intv)) { + return yaml_INT_TAG, int(intv) + } else { + return yaml_INT_TAG, intv + } + } + uintv, err := strconv.ParseUint(plain, 0, 64) + if err == nil { + return yaml_INT_TAG, uintv + } + floatv, err := strconv.ParseFloat(plain, 64) + if err == nil { + return yaml_FLOAT_TAG, floatv + } + if strings.HasPrefix(plain, "0b") { + intv, err := strconv.ParseInt(plain[2:], 2, 64) + if err == nil { + if intv == int64(int(intv)) { + return yaml_INT_TAG, int(intv) + } else { + return yaml_INT_TAG, intv + } + } + uintv, err := strconv.ParseUint(plain[2:], 2, 64) + if err == nil { + return yaml_INT_TAG, uintv + } + } else if strings.HasPrefix(plain, "-0b") { + intv, err := strconv.ParseInt(plain[3:], 2, 64) + if err == nil { + if intv == int64(int(intv)) { + return yaml_INT_TAG, -int(intv) + } else { + return yaml_INT_TAG, -intv + } + } + } + // XXX Handle timestamps here. + + default: + panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")") + } + } + if tag == yaml_BINARY_TAG { + return yaml_BINARY_TAG, in + } + if utf8.ValidString(in) { + return yaml_STR_TAG, in + } + return yaml_BINARY_TAG, encodeBase64(in) +} + +// encodeBase64 encodes s as base64 that is broken up into multiple lines +// as appropriate for the resulting length. +func encodeBase64(s string) string { + const lineLen = 70 + encLen := base64.StdEncoding.EncodedLen(len(s)) + lines := encLen/lineLen + 1 + buf := make([]byte, encLen*2+lines) + in := buf[0:encLen] + out := buf[encLen:] + base64.StdEncoding.Encode(in, []byte(s)) + k := 0 + for i := 0; i < len(in); i += lineLen { + j := i + lineLen + if j > len(in) { + j = len(in) + } + k += copy(out[k:], in[i:j]) + if lines > 1 { + out[k] = '\n' + k++ + } + } + return string(out[:k]) +} diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/scannerc.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/scannerc.go new file mode 100644 index 00000000..fe93b190 --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/scannerc.go @@ -0,0 +1,2710 @@ +package yaml + +import ( + "bytes" + "fmt" +) + +// Introduction +// ************ +// +// The following notes assume that you are familiar with the YAML specification +// (http://yaml.org/spec/cvs/current.html). We mostly follow it, although in +// some cases we are less restrictive that it requires. +// +// The process of transforming a YAML stream into a sequence of events is +// divided on two steps: Scanning and Parsing. +// +// The Scanner transforms the input stream into a sequence of tokens, while the +// parser transform the sequence of tokens produced by the Scanner into a +// sequence of parsing events. +// +// The Scanner is rather clever and complicated. The Parser, on the contrary, +// is a straightforward implementation of a recursive-descendant parser (or, +// LL(1) parser, as it is usually called). +// +// Actually there are two issues of Scanning that might be called "clever", the +// rest is quite straightforward. The issues are "block collection start" and +// "simple keys". Both issues are explained below in details. +// +// Here the Scanning step is explained and implemented. We start with the list +// of all the tokens produced by the Scanner together with short descriptions. +// +// Now, tokens: +// +// STREAM-START(encoding) # The stream start. +// STREAM-END # The stream end. +// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive. +// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive. +// DOCUMENT-START # '---' +// DOCUMENT-END # '...' +// BLOCK-SEQUENCE-START # Indentation increase denoting a block +// BLOCK-MAPPING-START # sequence or a block mapping. +// BLOCK-END # Indentation decrease. +// FLOW-SEQUENCE-START # '[' +// FLOW-SEQUENCE-END # ']' +// BLOCK-SEQUENCE-START # '{' +// BLOCK-SEQUENCE-END # '}' +// BLOCK-ENTRY # '-' +// FLOW-ENTRY # ',' +// KEY # '?' or nothing (simple keys). +// VALUE # ':' +// ALIAS(anchor) # '*anchor' +// ANCHOR(anchor) # '&anchor' +// TAG(handle,suffix) # '!handle!suffix' +// SCALAR(value,style) # A scalar. +// +// The following two tokens are "virtual" tokens denoting the beginning and the +// end of the stream: +// +// STREAM-START(encoding) +// STREAM-END +// +// We pass the information about the input stream encoding with the +// STREAM-START token. +// +// The next two tokens are responsible for tags: +// +// VERSION-DIRECTIVE(major,minor) +// TAG-DIRECTIVE(handle,prefix) +// +// Example: +// +// %YAML 1.1 +// %TAG ! !foo +// %TAG !yaml! tag:yaml.org,2002: +// --- +// +// The correspoding sequence of tokens: +// +// STREAM-START(utf-8) +// VERSION-DIRECTIVE(1,1) +// TAG-DIRECTIVE("!","!foo") +// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:") +// DOCUMENT-START +// STREAM-END +// +// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole +// line. +// +// The document start and end indicators are represented by: +// +// DOCUMENT-START +// DOCUMENT-END +// +// Note that if a YAML stream contains an implicit document (without '---' +// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be +// produced. +// +// In the following examples, we present whole documents together with the +// produced tokens. +// +// 1. An implicit document: +// +// 'a scalar' +// +// Tokens: +// +// STREAM-START(utf-8) +// SCALAR("a scalar",single-quoted) +// STREAM-END +// +// 2. An explicit document: +// +// --- +// 'a scalar' +// ... +// +// Tokens: +// +// STREAM-START(utf-8) +// DOCUMENT-START +// SCALAR("a scalar",single-quoted) +// DOCUMENT-END +// STREAM-END +// +// 3. Several documents in a stream: +// +// 'a scalar' +// --- +// 'another scalar' +// --- +// 'yet another scalar' +// +// Tokens: +// +// STREAM-START(utf-8) +// SCALAR("a scalar",single-quoted) +// DOCUMENT-START +// SCALAR("another scalar",single-quoted) +// DOCUMENT-START +// SCALAR("yet another scalar",single-quoted) +// STREAM-END +// +// We have already introduced the SCALAR token above. The following tokens are +// used to describe aliases, anchors, tag, and scalars: +// +// ALIAS(anchor) +// ANCHOR(anchor) +// TAG(handle,suffix) +// SCALAR(value,style) +// +// The following series of examples illustrate the usage of these tokens: +// +// 1. A recursive sequence: +// +// &A [ *A ] +// +// Tokens: +// +// STREAM-START(utf-8) +// ANCHOR("A") +// FLOW-SEQUENCE-START +// ALIAS("A") +// FLOW-SEQUENCE-END +// STREAM-END +// +// 2. A tagged scalar: +// +// !!float "3.14" # A good approximation. +// +// Tokens: +// +// STREAM-START(utf-8) +// TAG("!!","float") +// SCALAR("3.14",double-quoted) +// STREAM-END +// +// 3. Various scalar styles: +// +// --- # Implicit empty plain scalars do not produce tokens. +// --- a plain scalar +// --- 'a single-quoted scalar' +// --- "a double-quoted scalar" +// --- |- +// a literal scalar +// --- >- +// a folded +// scalar +// +// Tokens: +// +// STREAM-START(utf-8) +// DOCUMENT-START +// DOCUMENT-START +// SCALAR("a plain scalar",plain) +// DOCUMENT-START +// SCALAR("a single-quoted scalar",single-quoted) +// DOCUMENT-START +// SCALAR("a double-quoted scalar",double-quoted) +// DOCUMENT-START +// SCALAR("a literal scalar",literal) +// DOCUMENT-START +// SCALAR("a folded scalar",folded) +// STREAM-END +// +// Now it's time to review collection-related tokens. We will start with +// flow collections: +// +// FLOW-SEQUENCE-START +// FLOW-SEQUENCE-END +// FLOW-MAPPING-START +// FLOW-MAPPING-END +// FLOW-ENTRY +// KEY +// VALUE +// +// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and +// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}' +// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the +// indicators '?' and ':', which are used for denoting mapping keys and values, +// are represented by the KEY and VALUE tokens. +// +// The following examples show flow collections: +// +// 1. A flow sequence: +// +// [item 1, item 2, item 3] +// +// Tokens: +// +// STREAM-START(utf-8) +// FLOW-SEQUENCE-START +// SCALAR("item 1",plain) +// FLOW-ENTRY +// SCALAR("item 2",plain) +// FLOW-ENTRY +// SCALAR("item 3",plain) +// FLOW-SEQUENCE-END +// STREAM-END +// +// 2. A flow mapping: +// +// { +// a simple key: a value, # Note that the KEY token is produced. +// ? a complex key: another value, +// } +// +// Tokens: +// +// STREAM-START(utf-8) +// FLOW-MAPPING-START +// KEY +// SCALAR("a simple key",plain) +// VALUE +// SCALAR("a value",plain) +// FLOW-ENTRY +// KEY +// SCALAR("a complex key",plain) +// VALUE +// SCALAR("another value",plain) +// FLOW-ENTRY +// FLOW-MAPPING-END +// STREAM-END +// +// A simple key is a key which is not denoted by the '?' indicator. Note that +// the Scanner still produce the KEY token whenever it encounters a simple key. +// +// For scanning block collections, the following tokens are used (note that we +// repeat KEY and VALUE here): +// +// BLOCK-SEQUENCE-START +// BLOCK-MAPPING-START +// BLOCK-END +// BLOCK-ENTRY +// KEY +// VALUE +// +// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation +// increase that precedes a block collection (cf. the INDENT token in Python). +// The token BLOCK-END denote indentation decrease that ends a block collection +// (cf. the DEDENT token in Python). However YAML has some syntax pecularities +// that makes detections of these tokens more complex. +// +// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators +// '-', '?', and ':' correspondingly. +// +// The following examples show how the tokens BLOCK-SEQUENCE-START, +// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner: +// +// 1. Block sequences: +// +// - item 1 +// - item 2 +// - +// - item 3.1 +// - item 3.2 +// - +// key 1: value 1 +// key 2: value 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-ENTRY +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 3.1",plain) +// BLOCK-ENTRY +// SCALAR("item 3.2",plain) +// BLOCK-END +// BLOCK-ENTRY +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// 2. Block mappings: +// +// a simple key: a value # The KEY token is produced here. +// ? a complex key +// : another value +// a mapping: +// key 1: value 1 +// key 2: value 2 +// a sequence: +// - item 1 +// - item 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-MAPPING-START +// KEY +// SCALAR("a simple key",plain) +// VALUE +// SCALAR("a value",plain) +// KEY +// SCALAR("a complex key",plain) +// VALUE +// SCALAR("another value",plain) +// KEY +// SCALAR("a mapping",plain) +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// KEY +// SCALAR("a sequence",plain) +// VALUE +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// YAML does not always require to start a new block collection from a new +// line. If the current line contains only '-', '?', and ':' indicators, a new +// block collection may start at the current line. The following examples +// illustrate this case: +// +// 1. Collections in a sequence: +// +// - - item 1 +// - item 2 +// - key 1: value 1 +// key 2: value 2 +// - ? complex key +// : complex value +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// BLOCK-ENTRY +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// BLOCK-ENTRY +// BLOCK-MAPPING-START +// KEY +// SCALAR("complex key") +// VALUE +// SCALAR("complex value") +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// 2. Collections in a mapping: +// +// ? a sequence +// : - item 1 +// - item 2 +// ? a mapping +// : key 1: value 1 +// key 2: value 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-MAPPING-START +// KEY +// SCALAR("a sequence",plain) +// VALUE +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// KEY +// SCALAR("a mapping",plain) +// VALUE +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// YAML also permits non-indented sequences if they are included into a block +// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced: +// +// key: +// - item 1 # BLOCK-SEQUENCE-START is NOT produced here. +// - item 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-MAPPING-START +// KEY +// SCALAR("key",plain) +// VALUE +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// + +// Ensure that the buffer contains the required number of characters. +// Return true on success, false on failure (reader error or memory error). +func cache(parser *yaml_parser_t, length int) bool { + // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B) + return parser.unread >= length || yaml_parser_update_buffer(parser, length) +} + +// Advance the buffer pointer. +func skip(parser *yaml_parser_t) { + parser.mark.index++ + parser.mark.column++ + parser.unread-- + parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) +} + +func skip_line(parser *yaml_parser_t) { + if is_crlf(parser.buffer, parser.buffer_pos) { + parser.mark.index += 2 + parser.mark.column = 0 + parser.mark.line++ + parser.unread -= 2 + parser.buffer_pos += 2 + } else if is_break(parser.buffer, parser.buffer_pos) { + parser.mark.index++ + parser.mark.column = 0 + parser.mark.line++ + parser.unread-- + parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) + } +} + +// Copy a character to a string buffer and advance pointers. +func read(parser *yaml_parser_t, s []byte) []byte { + w := width(parser.buffer[parser.buffer_pos]) + if w == 0 { + panic("invalid character sequence") + } + if len(s) == 0 { + s = make([]byte, 0, 32) + } + if w == 1 && len(s)+w <= cap(s) { + s = s[:len(s)+1] + s[len(s)-1] = parser.buffer[parser.buffer_pos] + parser.buffer_pos++ + } else { + s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...) + parser.buffer_pos += w + } + parser.mark.index++ + parser.mark.column++ + parser.unread-- + return s +} + +// Copy a line break character to a string buffer and advance pointers. +func read_line(parser *yaml_parser_t, s []byte) []byte { + buf := parser.buffer + pos := parser.buffer_pos + switch { + case buf[pos] == '\r' && buf[pos+1] == '\n': + // CR LF . LF + s = append(s, '\n') + parser.buffer_pos += 2 + parser.mark.index++ + parser.unread-- + case buf[pos] == '\r' || buf[pos] == '\n': + // CR|LF . LF + s = append(s, '\n') + parser.buffer_pos += 1 + case buf[pos] == '\xC2' && buf[pos+1] == '\x85': + // NEL . LF + s = append(s, '\n') + parser.buffer_pos += 2 + case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'): + // LS|PS . LS|PS + s = append(s, buf[parser.buffer_pos:pos+3]...) + parser.buffer_pos += 3 + default: + return s + } + parser.mark.index++ + parser.mark.column = 0 + parser.mark.line++ + parser.unread-- + return s +} + +// Get the next token. +func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool { + // Erase the token object. + *token = yaml_token_t{} // [Go] Is this necessary? + + // No tokens after STREAM-END or error. + if parser.stream_end_produced || parser.error != yaml_NO_ERROR { + return true + } + + // Ensure that the tokens queue contains enough tokens. + if !parser.token_available { + if !yaml_parser_fetch_more_tokens(parser) { + return false + } + } + + // Fetch the next token from the queue. + *token = parser.tokens[parser.tokens_head] + parser.tokens_head++ + parser.tokens_parsed++ + parser.token_available = false + + if token.typ == yaml_STREAM_END_TOKEN { + parser.stream_end_produced = true + } + return true +} + +// Set the scanner error and return false. +func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool { + parser.error = yaml_SCANNER_ERROR + parser.context = context + parser.context_mark = context_mark + parser.problem = problem + parser.problem_mark = parser.mark + return false +} + +func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool { + context := "while parsing a tag" + if directive { + context = "while parsing a %TAG directive" + } + return yaml_parser_set_scanner_error(parser, context, context_mark, "did not find URI escaped octet") +} + +func trace(args ...interface{}) func() { + pargs := append([]interface{}{"+++"}, args...) + fmt.Println(pargs...) + pargs = append([]interface{}{"---"}, args...) + return func() { fmt.Println(pargs...) } +} + +// Ensure that the tokens queue contains at least one token which can be +// returned to the Parser. +func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool { + // While we need more tokens to fetch, do it. + for { + // Check if we really need to fetch more tokens. + need_more_tokens := false + + if parser.tokens_head == len(parser.tokens) { + // Queue is empty. + need_more_tokens = true + } else { + // Check if any potential simple key may occupy the head position. + if !yaml_parser_stale_simple_keys(parser) { + return false + } + + for i := range parser.simple_keys { + simple_key := &parser.simple_keys[i] + if simple_key.possible && simple_key.token_number == parser.tokens_parsed { + need_more_tokens = true + break + } + } + } + + // We are finished. + if !need_more_tokens { + break + } + // Fetch the next token. + if !yaml_parser_fetch_next_token(parser) { + return false + } + } + + parser.token_available = true + return true +} + +// The dispatcher for token fetchers. +func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool { + // Ensure that the buffer is initialized. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // Check if we just started scanning. Fetch STREAM-START then. + if !parser.stream_start_produced { + return yaml_parser_fetch_stream_start(parser) + } + + // Eat whitespaces and comments until we reach the next token. + if !yaml_parser_scan_to_next_token(parser) { + return false + } + + // Remove obsolete potential simple keys. + if !yaml_parser_stale_simple_keys(parser) { + return false + } + + // Check the indentation level against the current column. + if !yaml_parser_unroll_indent(parser, parser.mark.column) { + return false + } + + // Ensure that the buffer contains at least 4 characters. 4 is the length + // of the longest indicators ('--- ' and '... '). + if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { + return false + } + + // Is it the end of the stream? + if is_z(parser.buffer, parser.buffer_pos) { + return yaml_parser_fetch_stream_end(parser) + } + + // Is it a directive? + if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' { + return yaml_parser_fetch_directive(parser) + } + + buf := parser.buffer + pos := parser.buffer_pos + + // Is it the document start indicator? + if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) { + return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN) + } + + // Is it the document end indicator? + if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) { + return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN) + } + + // Is it the flow sequence start indicator? + if buf[pos] == '[' { + return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN) + } + + // Is it the flow mapping start indicator? + if parser.buffer[parser.buffer_pos] == '{' { + return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN) + } + + // Is it the flow sequence end indicator? + if parser.buffer[parser.buffer_pos] == ']' { + return yaml_parser_fetch_flow_collection_end(parser, + yaml_FLOW_SEQUENCE_END_TOKEN) + } + + // Is it the flow mapping end indicator? + if parser.buffer[parser.buffer_pos] == '}' { + return yaml_parser_fetch_flow_collection_end(parser, + yaml_FLOW_MAPPING_END_TOKEN) + } + + // Is it the flow entry indicator? + if parser.buffer[parser.buffer_pos] == ',' { + return yaml_parser_fetch_flow_entry(parser) + } + + // Is it the block entry indicator? + if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) { + return yaml_parser_fetch_block_entry(parser) + } + + // Is it the key indicator? + if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { + return yaml_parser_fetch_key(parser) + } + + // Is it the value indicator? + if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { + return yaml_parser_fetch_value(parser) + } + + // Is it an alias? + if parser.buffer[parser.buffer_pos] == '*' { + return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN) + } + + // Is it an anchor? + if parser.buffer[parser.buffer_pos] == '&' { + return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN) + } + + // Is it a tag? + if parser.buffer[parser.buffer_pos] == '!' { + return yaml_parser_fetch_tag(parser) + } + + // Is it a literal scalar? + if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 { + return yaml_parser_fetch_block_scalar(parser, true) + } + + // Is it a folded scalar? + if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 { + return yaml_parser_fetch_block_scalar(parser, false) + } + + // Is it a single-quoted scalar? + if parser.buffer[parser.buffer_pos] == '\'' { + return yaml_parser_fetch_flow_scalar(parser, true) + } + + // Is it a double-quoted scalar? + if parser.buffer[parser.buffer_pos] == '"' { + return yaml_parser_fetch_flow_scalar(parser, false) + } + + // Is it a plain scalar? + // + // A plain scalar may start with any non-blank characters except + // + // '-', '?', ':', ',', '[', ']', '{', '}', + // '#', '&', '*', '!', '|', '>', '\'', '\"', + // '%', '@', '`'. + // + // In the block context (and, for the '-' indicator, in the flow context + // too), it may also start with the characters + // + // '-', '?', ':' + // + // if it is followed by a non-space character. + // + // The last rule is more restrictive than the specification requires. + // [Go] Make this logic more reasonable. + //switch parser.buffer[parser.buffer_pos] { + //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`': + //} + if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' || + parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' || + parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' || + parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || + parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' || + parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' || + parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' || + parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' || + parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' || + parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') || + (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) || + (parser.flow_level == 0 && + (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') && + !is_blankz(parser.buffer, parser.buffer_pos+1)) { + return yaml_parser_fetch_plain_scalar(parser) + } + + // If we don't determine the token type so far, it is an error. + return yaml_parser_set_scanner_error(parser, + "while scanning for the next token", parser.mark, + "found character that cannot start any token") +} + +// Check the list of potential simple keys and remove the positions that +// cannot contain simple keys anymore. +func yaml_parser_stale_simple_keys(parser *yaml_parser_t) bool { + // Check for a potential simple key for each flow level. + for i := range parser.simple_keys { + simple_key := &parser.simple_keys[i] + + // The specification requires that a simple key + // + // - is limited to a single line, + // - is shorter than 1024 characters. + if simple_key.possible && (simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index) { + + // Check if the potential simple key to be removed is required. + if simple_key.required { + return yaml_parser_set_scanner_error(parser, + "while scanning a simple key", simple_key.mark, + "could not find expected ':'") + } + simple_key.possible = false + } + } + return true +} + +// Check if a simple key may start at the current position and add it if +// needed. +func yaml_parser_save_simple_key(parser *yaml_parser_t) bool { + // A simple key is required at the current position if the scanner is in + // the block context and the current column coincides with the indentation + // level. + + required := parser.flow_level == 0 && parser.indent == parser.mark.column + + // A simple key is required only when it is the first token in the current + // line. Therefore it is always allowed. But we add a check anyway. + if required && !parser.simple_key_allowed { + panic("should not happen") + } + + // + // If the current position may start a simple key, save it. + // + if parser.simple_key_allowed { + simple_key := yaml_simple_key_t{ + possible: true, + required: required, + token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), + } + simple_key.mark = parser.mark + + if !yaml_parser_remove_simple_key(parser) { + return false + } + parser.simple_keys[len(parser.simple_keys)-1] = simple_key + } + return true +} + +// Remove a potential simple key at the current flow level. +func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool { + i := len(parser.simple_keys) - 1 + if parser.simple_keys[i].possible { + // If the key is required, it is an error. + if parser.simple_keys[i].required { + return yaml_parser_set_scanner_error(parser, + "while scanning a simple key", parser.simple_keys[i].mark, + "could not find expected ':'") + } + } + // Remove the key from the stack. + parser.simple_keys[i].possible = false + return true +} + +// Increase the flow level and resize the simple key list if needed. +func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { + // Reset the simple key on the next level. + parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) + + // Increase the flow level. + parser.flow_level++ + return true +} + +// Decrease the flow level. +func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool { + if parser.flow_level > 0 { + parser.flow_level-- + parser.simple_keys = parser.simple_keys[:len(parser.simple_keys)-1] + } + return true +} + +// Push the current indentation level to the stack and set the new level +// the current column is greater than the indentation level. In this case, +// append or insert the specified token into the token queue. +func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool { + // In the flow context, do nothing. + if parser.flow_level > 0 { + return true + } + + if parser.indent < column { + // Push the current indentation level to the stack and set the new + // indentation level. + parser.indents = append(parser.indents, parser.indent) + parser.indent = column + + // Create a token and insert it into the queue. + token := yaml_token_t{ + typ: typ, + start_mark: mark, + end_mark: mark, + } + if number > -1 { + number -= parser.tokens_parsed + } + yaml_insert_token(parser, number, &token) + } + return true +} + +// Pop indentation levels from the indents stack until the current level +// becomes less or equal to the column. For each intendation level, append +// the BLOCK-END token. +func yaml_parser_unroll_indent(parser *yaml_parser_t, column int) bool { + // In the flow context, do nothing. + if parser.flow_level > 0 { + return true + } + + // Loop through the intendation levels in the stack. + for parser.indent > column { + // Create a token and append it to the queue. + token := yaml_token_t{ + typ: yaml_BLOCK_END_TOKEN, + start_mark: parser.mark, + end_mark: parser.mark, + } + yaml_insert_token(parser, -1, &token) + + // Pop the indentation level. + parser.indent = parser.indents[len(parser.indents)-1] + parser.indents = parser.indents[:len(parser.indents)-1] + } + return true +} + +// Initialize the scanner and produce the STREAM-START token. +func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool { + + // Set the initial indentation. + parser.indent = -1 + + // Initialize the simple key stack. + parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) + + // A simple key is allowed at the beginning of the stream. + parser.simple_key_allowed = true + + // We have started. + parser.stream_start_produced = true + + // Create the STREAM-START token and append it to the queue. + token := yaml_token_t{ + typ: yaml_STREAM_START_TOKEN, + start_mark: parser.mark, + end_mark: parser.mark, + encoding: parser.encoding, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the STREAM-END token and shut down the scanner. +func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool { + + // Force new line. + if parser.mark.column != 0 { + parser.mark.column = 0 + parser.mark.line++ + } + + // Reset the indentation level. + if !yaml_parser_unroll_indent(parser, -1) { + return false + } + + // Reset simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + parser.simple_key_allowed = false + + // Create the STREAM-END token and append it to the queue. + token := yaml_token_t{ + typ: yaml_STREAM_END_TOKEN, + start_mark: parser.mark, + end_mark: parser.mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token. +func yaml_parser_fetch_directive(parser *yaml_parser_t) bool { + // Reset the indentation level. + if !yaml_parser_unroll_indent(parser, -1) { + return false + } + + // Reset simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + parser.simple_key_allowed = false + + // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. + token := yaml_token_t{} + if !yaml_parser_scan_directive(parser, &token) { + return false + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the DOCUMENT-START or DOCUMENT-END token. +func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // Reset the indentation level. + if !yaml_parser_unroll_indent(parser, -1) { + return false + } + + // Reset simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + parser.simple_key_allowed = false + + // Consume the token. + start_mark := parser.mark + + skip(parser) + skip(parser) + skip(parser) + + end_mark := parser.mark + + // Create the DOCUMENT-START or DOCUMENT-END token. + token := yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token. +func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // The indicators '[' and '{' may start a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // Increase the flow level. + if !yaml_parser_increase_flow_level(parser) { + return false + } + + // A simple key may follow the indicators '[' and '{'. + parser.simple_key_allowed = true + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. + token := yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token. +func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // Reset any potential simple key on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Decrease the flow level. + if !yaml_parser_decrease_flow_level(parser) { + return false + } + + // No simple keys after the indicators ']' and '}'. + parser.simple_key_allowed = false + + // Consume the token. + + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. + token := yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the FLOW-ENTRY token. +func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool { + // Reset any potential simple keys on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Simple keys are allowed after ','. + parser.simple_key_allowed = true + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the FLOW-ENTRY token and append it to the queue. + token := yaml_token_t{ + typ: yaml_FLOW_ENTRY_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the BLOCK-ENTRY token. +func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool { + // Check if the scanner is in the block context. + if parser.flow_level == 0 { + // Check if we are allowed to start a new entry. + if !parser.simple_key_allowed { + return yaml_parser_set_scanner_error(parser, "", parser.mark, + "block sequence entries are not allowed in this context") + } + // Add the BLOCK-SEQUENCE-START token if needed. + if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) { + return false + } + } else { + // It is an error for the '-' indicator to occur in the flow context, + // but we let the Parser detect and report about it because the Parser + // is able to point to the context. + } + + // Reset any potential simple keys on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Simple keys are allowed after '-'. + parser.simple_key_allowed = true + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the BLOCK-ENTRY token and append it to the queue. + token := yaml_token_t{ + typ: yaml_BLOCK_ENTRY_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the KEY token. +func yaml_parser_fetch_key(parser *yaml_parser_t) bool { + + // In the block context, additional checks are required. + if parser.flow_level == 0 { + // Check if we are allowed to start a new key (not nessesary simple). + if !parser.simple_key_allowed { + return yaml_parser_set_scanner_error(parser, "", parser.mark, + "mapping keys are not allowed in this context") + } + // Add the BLOCK-MAPPING-START token if needed. + if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { + return false + } + } + + // Reset any potential simple keys on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Simple keys are allowed after '?' in the block context. + parser.simple_key_allowed = parser.flow_level == 0 + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the KEY token and append it to the queue. + token := yaml_token_t{ + typ: yaml_KEY_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the VALUE token. +func yaml_parser_fetch_value(parser *yaml_parser_t) bool { + + simple_key := &parser.simple_keys[len(parser.simple_keys)-1] + + // Have we found a simple key? + if simple_key.possible { + // Create the KEY token and insert it into the queue. + token := yaml_token_t{ + typ: yaml_KEY_TOKEN, + start_mark: simple_key.mark, + end_mark: simple_key.mark, + } + yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token) + + // In the block context, we may need to add the BLOCK-MAPPING-START token. + if !yaml_parser_roll_indent(parser, simple_key.mark.column, + simple_key.token_number, + yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) { + return false + } + + // Remove the simple key. + simple_key.possible = false + + // A simple key cannot follow another simple key. + parser.simple_key_allowed = false + + } else { + // The ':' indicator follows a complex key. + + // In the block context, extra checks are required. + if parser.flow_level == 0 { + + // Check if we are allowed to start a complex value. + if !parser.simple_key_allowed { + return yaml_parser_set_scanner_error(parser, "", parser.mark, + "mapping values are not allowed in this context") + } + + // Add the BLOCK-MAPPING-START token if needed. + if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { + return false + } + } + + // Simple keys after ':' are allowed in the block context. + parser.simple_key_allowed = parser.flow_level == 0 + } + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the VALUE token and append it to the queue. + token := yaml_token_t{ + typ: yaml_VALUE_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the ALIAS or ANCHOR token. +func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // An anchor or an alias could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow an anchor or an alias. + parser.simple_key_allowed = false + + // Create the ALIAS or ANCHOR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_anchor(parser, &token, typ) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the TAG token. +func yaml_parser_fetch_tag(parser *yaml_parser_t) bool { + // A tag could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow a tag. + parser.simple_key_allowed = false + + // Create the TAG token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_tag(parser, &token) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens. +func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool { + // Remove any potential simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // A simple key may follow a block scalar. + parser.simple_key_allowed = true + + // Create the SCALAR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_block_scalar(parser, &token, literal) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens. +func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool { + // A plain scalar could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow a flow scalar. + parser.simple_key_allowed = false + + // Create the SCALAR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_flow_scalar(parser, &token, single) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the SCALAR(...,plain) token. +func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool { + // A plain scalar could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow a flow scalar. + parser.simple_key_allowed = false + + // Create the SCALAR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_plain_scalar(parser, &token) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Eat whitespaces and comments until the next token is found. +func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool { + + // Until the next token is not found. + for { + // Allow the BOM mark to start a line. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) { + skip(parser) + } + + // Eat whitespaces. + // Tabs are allowed: + // - in the flow context + // - in the block context, but not at the beginning of the line or + // after '-', '?', or ':' (complex value). + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Eat a comment until a line break. + if parser.buffer[parser.buffer_pos] == '#' { + for !is_breakz(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + } + + // If it is a line break, eat it. + if is_break(parser.buffer, parser.buffer_pos) { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + + // In the block context, a new line may start a simple key. + if parser.flow_level == 0 { + parser.simple_key_allowed = true + } + } else { + break // We have found a token. + } + } + + return true +} + +// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token. +// +// Scope: +// %YAML 1.1 # a comment \n +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// %TAG !yaml! tag:yaml.org,2002: \n +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// +func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool { + // Eat '%'. + start_mark := parser.mark + skip(parser) + + // Scan the directive name. + var name []byte + if !yaml_parser_scan_directive_name(parser, start_mark, &name) { + return false + } + + // Is it a YAML directive? + if bytes.Equal(name, []byte("YAML")) { + // Scan the VERSION directive value. + var major, minor int8 + if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) { + return false + } + end_mark := parser.mark + + // Create a VERSION-DIRECTIVE token. + *token = yaml_token_t{ + typ: yaml_VERSION_DIRECTIVE_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + major: major, + minor: minor, + } + + // Is it a TAG directive? + } else if bytes.Equal(name, []byte("TAG")) { + // Scan the TAG directive value. + var handle, prefix []byte + if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) { + return false + } + end_mark := parser.mark + + // Create a TAG-DIRECTIVE token. + *token = yaml_token_t{ + typ: yaml_TAG_DIRECTIVE_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: handle, + prefix: prefix, + } + + // Unknown directive. + } else { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "found uknown directive name") + return false + } + + // Eat the rest of the line including any comments. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + if parser.buffer[parser.buffer_pos] == '#' { + for !is_breakz(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + } + + // Check if we are at the end of the line. + if !is_breakz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "did not find expected comment or line break") + return false + } + + // Eat a line break. + if is_break(parser.buffer, parser.buffer_pos) { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + } + + return true +} + +// Scan the directive name. +// +// Scope: +// %YAML 1.1 # a comment \n +// ^^^^ +// %TAG !yaml! tag:yaml.org,2002: \n +// ^^^ +// +func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool { + // Consume the directive name. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + var s []byte + for is_alpha(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if the name is empty. + if len(s) == 0 { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "could not find expected directive name") + return false + } + + // Check for an blank character after the name. + if !is_blankz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "found unexpected non-alphabetical character") + return false + } + *name = s + return true +} + +// Scan the value of VERSION-DIRECTIVE. +// +// Scope: +// %YAML 1.1 # a comment \n +// ^^^^^^ +func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool { + // Eat whitespaces. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Consume the major version number. + if !yaml_parser_scan_version_directive_number(parser, start_mark, major) { + return false + } + + // Eat '.'. + if parser.buffer[parser.buffer_pos] != '.' { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "did not find expected digit or '.' character") + } + + skip(parser) + + // Consume the minor version number. + if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) { + return false + } + return true +} + +const max_number_length = 2 + +// Scan the version number of VERSION-DIRECTIVE. +// +// Scope: +// %YAML 1.1 # a comment \n +// ^ +// %YAML 1.1 # a comment \n +// ^ +func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool { + + // Repeat while the next character is digit. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + var value, length int8 + for is_digit(parser.buffer, parser.buffer_pos) { + // Check if the number is too long. + length++ + if length > max_number_length { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "found extremely long version number") + } + value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos)) + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if the number was present. + if length == 0 { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "did not find expected version number") + } + *number = value + return true +} + +// Scan the value of a TAG-DIRECTIVE token. +// +// Scope: +// %TAG !yaml! tag:yaml.org,2002: \n +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// +func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool { + var handle_value, prefix_value []byte + + // Eat whitespaces. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Scan a handle. + if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) { + return false + } + + // Expect a whitespace. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if !is_blank(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", + start_mark, "did not find expected whitespace") + return false + } + + // Eat whitespaces. + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Scan a prefix. + if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) { + return false + } + + // Expect a whitespace or line break. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if !is_blankz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", + start_mark, "did not find expected whitespace or line break") + return false + } + + *handle = handle_value + *prefix = prefix_value + return true +} + +func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool { + var s []byte + + // Eat the indicator character. + start_mark := parser.mark + skip(parser) + + // Consume the value. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_alpha(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + end_mark := parser.mark + + /* + * Check if length of the anchor is greater than 0 and it is followed by + * a whitespace character or one of the indicators: + * + * '?', ':', ',', ']', '}', '%', '@', '`'. + */ + + if len(s) == 0 || + !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' || + parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' || + parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' || + parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' || + parser.buffer[parser.buffer_pos] == '`') { + context := "while scanning an alias" + if typ == yaml_ANCHOR_TOKEN { + context = "while scanning an anchor" + } + yaml_parser_set_scanner_error(parser, context, start_mark, + "did not find expected alphabetic or numeric character") + return false + } + + // Create a token. + *token = yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + value: s, + } + + return true +} + +/* + * Scan a TAG token. + */ + +func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool { + var handle, suffix []byte + + start_mark := parser.mark + + // Check if the tag is in the canonical form. + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + if parser.buffer[parser.buffer_pos+1] == '<' { + // Keep the handle as '' + + // Eat '!<' + skip(parser) + skip(parser) + + // Consume the tag value. + if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { + return false + } + + // Check for '>' and eat it. + if parser.buffer[parser.buffer_pos] != '>' { + yaml_parser_set_scanner_error(parser, "while scanning a tag", + start_mark, "did not find the expected '>'") + return false + } + + skip(parser) + } else { + // The tag has either the '!suffix' or the '!handle!suffix' form. + + // First, try to scan a handle. + if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) { + return false + } + + // Check if it is, indeed, handle. + if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' { + // Scan the suffix now. + if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { + return false + } + } else { + // It wasn't a handle after all. Scan the rest of the tag. + if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) { + return false + } + + // Set the handle to '!'. + handle = []byte{'!'} + + // A special case: the '!' tag. Set the handle to '' and the + // suffix to '!'. + if len(suffix) == 0 { + handle, suffix = suffix, handle + } + } + } + + // Check the character which ends the tag. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if !is_blankz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a tag", + start_mark, "did not find expected whitespace or line break") + return false + } + + end_mark := parser.mark + + // Create a token. + *token = yaml_token_t{ + typ: yaml_TAG_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: handle, + suffix: suffix, + } + return true +} + +// Scan a tag handle. +func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool { + // Check the initial '!' character. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if parser.buffer[parser.buffer_pos] != '!' { + yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find expected '!'") + return false + } + + var s []byte + + // Copy the '!' character. + s = read(parser, s) + + // Copy all subsequent alphabetical and numerical characters. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for is_alpha(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if the trailing character is '!' and copy it. + if parser.buffer[parser.buffer_pos] == '!' { + s = read(parser, s) + } else { + // It's either the '!' tag or not really a tag handle. If it's a %TAG + // directive, it's an error. If it's a tag token, it must be a part of URI. + if directive && !(s[0] == '!' && s[1] == 0) { + yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find expected '!'") + return false + } + } + + *handle = s + return true +} + +// Scan a tag. +func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool { + //size_t length = head ? strlen((char *)head) : 0 + var s []byte + + // Copy the head if needed. + // + // Note that we don't copy the leading '!' character. + if len(head) > 1 { + s = append(s, head[1:]...) + } + + // Scan the tag. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // The set of characters that may appear in URI is as follows: + // + // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&', + // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']', + // '%'. + // [Go] Convert this into more reasonable logic. + for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' || + parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' || + parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' || + parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' || + parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' || + parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' || + parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' || + parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' || + parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' || + parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' || + parser.buffer[parser.buffer_pos] == '%' { + // Check if it is a URI-escape sequence. + if parser.buffer[parser.buffer_pos] == '%' { + if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) { + return false + } + } else { + s = read(parser, s) + } + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if the tag is non-empty. + if len(s) == 0 { + yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find expected tag URI") + return false + } + *uri = s + return true +} + +// Decode an URI-escape sequence corresponding to a single UTF-8 character. +func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool { + + // Decode the required number of characters. + w := 1024 + for w > 0 { + // Check for a URI-escaped octet. + if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { + return false + } + + if !(parser.buffer[parser.buffer_pos] == '%' && + is_hex(parser.buffer, parser.buffer_pos+1) && + is_hex(parser.buffer, parser.buffer_pos+2)) { + return yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find URI escaped octet") + } + + // Get the octet. + octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2)) + + // If it is the leading octet, determine the length of the UTF-8 sequence. + if w == 1024 { + w = width(octet) + if w == 0 { + return yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "found an incorrect leading UTF-8 octet") + } + } else { + // Check if the trailing octet is correct. + if octet&0xC0 != 0x80 { + return yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "found an incorrect trailing UTF-8 octet") + } + } + + // Copy the octet and move the pointers. + *s = append(*s, octet) + skip(parser) + skip(parser) + skip(parser) + w-- + } + return true +} + +// Scan a block scalar. +func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool { + // Eat the indicator '|' or '>'. + start_mark := parser.mark + skip(parser) + + // Scan the additional block scalar indicators. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // Check for a chomping indicator. + var chomping, increment int + if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { + // Set the chomping method and eat the indicator. + if parser.buffer[parser.buffer_pos] == '+' { + chomping = +1 + } else { + chomping = -1 + } + skip(parser) + + // Check for an indentation indicator. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if is_digit(parser.buffer, parser.buffer_pos) { + // Check that the intendation is greater than 0. + if parser.buffer[parser.buffer_pos] == '0' { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found an intendation indicator equal to 0") + return false + } + + // Get the intendation level and eat the indicator. + increment = as_digit(parser.buffer, parser.buffer_pos) + skip(parser) + } + + } else if is_digit(parser.buffer, parser.buffer_pos) { + // Do the same as above, but in the opposite order. + + if parser.buffer[parser.buffer_pos] == '0' { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found an intendation indicator equal to 0") + return false + } + increment = as_digit(parser.buffer, parser.buffer_pos) + skip(parser) + + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { + if parser.buffer[parser.buffer_pos] == '+' { + chomping = +1 + } else { + chomping = -1 + } + skip(parser) + } + } + + // Eat whitespaces and comments to the end of the line. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + if parser.buffer[parser.buffer_pos] == '#' { + for !is_breakz(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + } + + // Check if we are at the end of the line. + if !is_breakz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "did not find expected comment or line break") + return false + } + + // Eat a line break. + if is_break(parser.buffer, parser.buffer_pos) { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + } + + end_mark := parser.mark + + // Set the intendation level if it was specified. + var indent int + if increment > 0 { + if parser.indent >= 0 { + indent = parser.indent + increment + } else { + indent = increment + } + } + + // Scan the leading line breaks and determine the indentation level if needed. + var s, leading_break, trailing_breaks []byte + if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { + return false + } + + // Scan the block scalar content. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + var leading_blank, trailing_blank bool + for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) { + // We are at the beginning of a non-empty line. + + // Is it a trailing whitespace? + trailing_blank = is_blank(parser.buffer, parser.buffer_pos) + + // Check if we need to fold the leading line break. + if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' { + // Do we need to join the lines by space? + if len(trailing_breaks) == 0 { + s = append(s, ' ') + } + } else { + s = append(s, leading_break...) + } + leading_break = leading_break[:0] + + // Append the remaining line breaks. + s = append(s, trailing_breaks...) + trailing_breaks = trailing_breaks[:0] + + // Is it a leading whitespace? + leading_blank = is_blank(parser.buffer, parser.buffer_pos) + + // Consume the current line. + for !is_breakz(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Consume the line break. + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + leading_break = read_line(parser, leading_break) + + // Eat the following intendation spaces and line breaks. + if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { + return false + } + } + + // Chomp the tail. + if chomping != -1 { + s = append(s, leading_break...) + } + if chomping == 1 { + s = append(s, trailing_breaks...) + } + + // Create a token. + *token = yaml_token_t{ + typ: yaml_SCALAR_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: s, + style: yaml_LITERAL_SCALAR_STYLE, + } + if !literal { + token.style = yaml_FOLDED_SCALAR_STYLE + } + return true +} + +// Scan intendation spaces and line breaks for a block scalar. Determine the +// intendation level if needed. +func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool { + *end_mark = parser.mark + + // Eat the intendation spaces and line breaks. + max_indent := 0 + for { + // Eat the intendation spaces. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + if parser.mark.column > max_indent { + max_indent = parser.mark.column + } + + // Check for a tab character messing the intendation. + if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) { + return yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found a tab character where an intendation space is expected") + } + + // Have we found a non-empty line? + if !is_break(parser.buffer, parser.buffer_pos) { + break + } + + // Consume the line break. + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + // [Go] Should really be returning breaks instead. + *breaks = read_line(parser, *breaks) + *end_mark = parser.mark + } + + // Determine the indentation level if needed. + if *indent == 0 { + *indent = max_indent + if *indent < parser.indent+1 { + *indent = parser.indent + 1 + } + if *indent < 1 { + *indent = 1 + } + } + return true +} + +// Scan a quoted scalar. +func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool { + // Eat the left quote. + start_mark := parser.mark + skip(parser) + + // Consume the content of the quoted scalar. + var s, leading_break, trailing_breaks, whitespaces []byte + for { + // Check that there are no document indicators at the beginning of the line. + if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { + return false + } + + if parser.mark.column == 0 && + ((parser.buffer[parser.buffer_pos+0] == '-' && + parser.buffer[parser.buffer_pos+1] == '-' && + parser.buffer[parser.buffer_pos+2] == '-') || + (parser.buffer[parser.buffer_pos+0] == '.' && + parser.buffer[parser.buffer_pos+1] == '.' && + parser.buffer[parser.buffer_pos+2] == '.')) && + is_blankz(parser.buffer, parser.buffer_pos+3) { + yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", + start_mark, "found unexpected document indicator") + return false + } + + // Check for EOF. + if is_z(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", + start_mark, "found unexpected end of stream") + return false + } + + // Consume non-blank characters. + leading_blanks := false + for !is_blankz(parser.buffer, parser.buffer_pos) { + if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' { + // Is is an escaped single quote. + s = append(s, '\'') + skip(parser) + skip(parser) + + } else if single && parser.buffer[parser.buffer_pos] == '\'' { + // It is a right single quote. + break + } else if !single && parser.buffer[parser.buffer_pos] == '"' { + // It is a right double quote. + break + + } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) { + // It is an escaped line break. + if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { + return false + } + skip(parser) + skip_line(parser) + leading_blanks = true + break + + } else if !single && parser.buffer[parser.buffer_pos] == '\\' { + // It is an escape sequence. + code_length := 0 + + // Check the escape character. + switch parser.buffer[parser.buffer_pos+1] { + case '0': + s = append(s, 0) + case 'a': + s = append(s, '\x07') + case 'b': + s = append(s, '\x08') + case 't', '\t': + s = append(s, '\x09') + case 'n': + s = append(s, '\x0A') + case 'v': + s = append(s, '\x0B') + case 'f': + s = append(s, '\x0C') + case 'r': + s = append(s, '\x0D') + case 'e': + s = append(s, '\x1B') + case ' ': + s = append(s, '\x20') + case '"': + s = append(s, '"') + case '\'': + s = append(s, '\'') + case '\\': + s = append(s, '\\') + case 'N': // NEL (#x85) + s = append(s, '\xC2') + s = append(s, '\x85') + case '_': // #xA0 + s = append(s, '\xC2') + s = append(s, '\xA0') + case 'L': // LS (#x2028) + s = append(s, '\xE2') + s = append(s, '\x80') + s = append(s, '\xA8') + case 'P': // PS (#x2029) + s = append(s, '\xE2') + s = append(s, '\x80') + s = append(s, '\xA9') + case 'x': + code_length = 2 + case 'u': + code_length = 4 + case 'U': + code_length = 8 + default: + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "found unknown escape character") + return false + } + + skip(parser) + skip(parser) + + // Consume an arbitrary escape code. + if code_length > 0 { + var value int + + // Scan the character value. + if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) { + return false + } + for k := 0; k < code_length; k++ { + if !is_hex(parser.buffer, parser.buffer_pos+k) { + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "did not find expected hexdecimal number") + return false + } + value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k) + } + + // Check the value and write the character. + if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF { + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "found invalid Unicode character escape code") + return false + } + if value <= 0x7F { + s = append(s, byte(value)) + } else if value <= 0x7FF { + s = append(s, byte(0xC0+(value>>6))) + s = append(s, byte(0x80+(value&0x3F))) + } else if value <= 0xFFFF { + s = append(s, byte(0xE0+(value>>12))) + s = append(s, byte(0x80+((value>>6)&0x3F))) + s = append(s, byte(0x80+(value&0x3F))) + } else { + s = append(s, byte(0xF0+(value>>18))) + s = append(s, byte(0x80+((value>>12)&0x3F))) + s = append(s, byte(0x80+((value>>6)&0x3F))) + s = append(s, byte(0x80+(value&0x3F))) + } + + // Advance the pointer. + for k := 0; k < code_length; k++ { + skip(parser) + } + } + } else { + // It is a non-escaped non-blank character. + s = read(parser, s) + } + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + } + + // Check if we are at the end of the scalar. + if single { + if parser.buffer[parser.buffer_pos] == '\'' { + break + } + } else { + if parser.buffer[parser.buffer_pos] == '"' { + break + } + } + + // Consume blank characters. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { + if is_blank(parser.buffer, parser.buffer_pos) { + // Consume a space or a tab character. + if !leading_blanks { + whitespaces = read(parser, whitespaces) + } else { + skip(parser) + } + } else { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + // Check if it is a first line break. + if !leading_blanks { + whitespaces = whitespaces[:0] + leading_break = read_line(parser, leading_break) + leading_blanks = true + } else { + trailing_breaks = read_line(parser, trailing_breaks) + } + } + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Join the whitespaces or fold line breaks. + if leading_blanks { + // Do we need to fold line breaks? + if len(leading_break) > 0 && leading_break[0] == '\n' { + if len(trailing_breaks) == 0 { + s = append(s, ' ') + } else { + s = append(s, trailing_breaks...) + } + } else { + s = append(s, leading_break...) + s = append(s, trailing_breaks...) + } + trailing_breaks = trailing_breaks[:0] + leading_break = leading_break[:0] + } else { + s = append(s, whitespaces...) + whitespaces = whitespaces[:0] + } + } + + // Eat the right quote. + skip(parser) + end_mark := parser.mark + + // Create a token. + *token = yaml_token_t{ + typ: yaml_SCALAR_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: s, + style: yaml_SINGLE_QUOTED_SCALAR_STYLE, + } + if !single { + token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + return true +} + +// Scan a plain scalar. +func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool { + + var s, leading_break, trailing_breaks, whitespaces []byte + var leading_blanks bool + var indent = parser.indent + 1 + + start_mark := parser.mark + end_mark := parser.mark + + // Consume the content of the plain scalar. + for { + // Check for a document indicator. + if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { + return false + } + if parser.mark.column == 0 && + ((parser.buffer[parser.buffer_pos+0] == '-' && + parser.buffer[parser.buffer_pos+1] == '-' && + parser.buffer[parser.buffer_pos+2] == '-') || + (parser.buffer[parser.buffer_pos+0] == '.' && + parser.buffer[parser.buffer_pos+1] == '.' && + parser.buffer[parser.buffer_pos+2] == '.')) && + is_blankz(parser.buffer, parser.buffer_pos+3) { + break + } + + // Check for a comment. + if parser.buffer[parser.buffer_pos] == '#' { + break + } + + // Consume non-blank characters. + for !is_blankz(parser.buffer, parser.buffer_pos) { + + // Check for 'x:x' in the flow context. TODO: Fix the test "spec-08-13". + if parser.flow_level > 0 && + parser.buffer[parser.buffer_pos] == ':' && + !is_blankz(parser.buffer, parser.buffer_pos+1) { + yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", + start_mark, "found unexpected ':'") + return false + } + + // Check for indicators that may end a plain scalar. + if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) || + (parser.flow_level > 0 && + (parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == ':' || + parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' || + parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || + parser.buffer[parser.buffer_pos] == '}')) { + break + } + + // Check if we need to join whitespaces and breaks. + if leading_blanks || len(whitespaces) > 0 { + if leading_blanks { + // Do we need to fold line breaks? + if leading_break[0] == '\n' { + if len(trailing_breaks) == 0 { + s = append(s, ' ') + } else { + s = append(s, trailing_breaks...) + } + } else { + s = append(s, leading_break...) + s = append(s, trailing_breaks...) + } + trailing_breaks = trailing_breaks[:0] + leading_break = leading_break[:0] + leading_blanks = false + } else { + s = append(s, whitespaces...) + whitespaces = whitespaces[:0] + } + } + + // Copy the character. + s = read(parser, s) + + end_mark = parser.mark + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + } + + // Is it the end? + if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) { + break + } + + // Consume blank characters. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { + if is_blank(parser.buffer, parser.buffer_pos) { + + // Check for tab character that abuse intendation. + if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", + start_mark, "found a tab character that violate intendation") + return false + } + + // Consume a space or a tab character. + if !leading_blanks { + whitespaces = read(parser, whitespaces) + } else { + skip(parser) + } + } else { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + // Check if it is a first line break. + if !leading_blanks { + whitespaces = whitespaces[:0] + leading_break = read_line(parser, leading_break) + leading_blanks = true + } else { + trailing_breaks = read_line(parser, trailing_breaks) + } + } + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check intendation level. + if parser.flow_level == 0 && parser.mark.column < indent { + break + } + } + + // Create a token. + *token = yaml_token_t{ + typ: yaml_SCALAR_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: s, + style: yaml_PLAIN_SCALAR_STYLE, + } + + // Note that we change the 'simple_key_allowed' flag. + if leading_blanks { + parser.simple_key_allowed = true + } + return true +} diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/sorter.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/sorter.go new file mode 100644 index 00000000..5958822f --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/sorter.go @@ -0,0 +1,104 @@ +package yaml + +import ( + "reflect" + "unicode" +) + +type keyList []reflect.Value + +func (l keyList) Len() int { return len(l) } +func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } +func (l keyList) Less(i, j int) bool { + a := l[i] + b := l[j] + ak := a.Kind() + bk := b.Kind() + for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { + a = a.Elem() + ak = a.Kind() + } + for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { + b = b.Elem() + bk = b.Kind() + } + af, aok := keyFloat(a) + bf, bok := keyFloat(b) + if aok && bok { + if af != bf { + return af < bf + } + if ak != bk { + return ak < bk + } + return numLess(a, b) + } + if ak != reflect.String || bk != reflect.String { + return ak < bk + } + ar, br := []rune(a.String()), []rune(b.String()) + for i := 0; i < len(ar) && i < len(br); i++ { + if ar[i] == br[i] { + continue + } + al := unicode.IsLetter(ar[i]) + bl := unicode.IsLetter(br[i]) + if al && bl { + return ar[i] < br[i] + } + if al || bl { + return bl + } + var ai, bi int + var an, bn int64 + for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { + an = an*10 + int64(ar[ai]-'0') + } + for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { + bn = bn*10 + int64(br[bi]-'0') + } + if an != bn { + return an < bn + } + if ai != bi { + return ai < bi + } + return ar[i] < br[i] + } + return len(ar) < len(br) +} + +// keyFloat returns a float value for v if it is a number/bool +// and whether it is a number/bool or not. +func keyFloat(v reflect.Value) (f float64, ok bool) { + switch v.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return float64(v.Int()), true + case reflect.Float32, reflect.Float64: + return v.Float(), true + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return float64(v.Uint()), true + case reflect.Bool: + if v.Bool() { + return 1, true + } + return 0, true + } + return 0, false +} + +// numLess returns whether a < b. +// a and b must necessarily have the same kind. +func numLess(a, b reflect.Value) bool { + switch a.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return a.Int() < b.Int() + case reflect.Float32, reflect.Float64: + return a.Float() < b.Float() + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return a.Uint() < b.Uint() + case reflect.Bool: + return !a.Bool() && b.Bool() + } + panic("not a number") +} diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/suite_test.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/suite_test.go new file mode 100644 index 00000000..c5cf1ed4 --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/suite_test.go @@ -0,0 +1,12 @@ +package yaml_test + +import ( + . "gopkg.in/check.v1" + "testing" +) + +func Test(t *testing.T) { TestingT(t) } + +type S struct{} + +var _ = Suite(&S{}) diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/writerc.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/writerc.go new file mode 100644 index 00000000..190362f2 --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/writerc.go @@ -0,0 +1,89 @@ +package yaml + +// Set the writer error and return false. +func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { + emitter.error = yaml_WRITER_ERROR + emitter.problem = problem + return false +} + +// Flush the output buffer. +func yaml_emitter_flush(emitter *yaml_emitter_t) bool { + if emitter.write_handler == nil { + panic("write handler not set") + } + + // Check if the buffer is empty. + if emitter.buffer_pos == 0 { + return true + } + + // If the output encoding is UTF-8, we don't need to recode the buffer. + if emitter.encoding == yaml_UTF8_ENCODING { + if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { + return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) + } + emitter.buffer_pos = 0 + return true + } + + // Recode the buffer into the raw buffer. + var low, high int + if emitter.encoding == yaml_UTF16LE_ENCODING { + low, high = 0, 1 + } else { + high, low = 1, 0 + } + + pos := 0 + for pos < emitter.buffer_pos { + // See the "reader.c" code for more details on UTF-8 encoding. Note + // that we assume that the buffer contains a valid UTF-8 sequence. + + // Read the next UTF-8 character. + octet := emitter.buffer[pos] + + var w int + var value rune + switch { + case octet&0x80 == 0x00: + w, value = 1, rune(octet&0x7F) + case octet&0xE0 == 0xC0: + w, value = 2, rune(octet&0x1F) + case octet&0xF0 == 0xE0: + w, value = 3, rune(octet&0x0F) + case octet&0xF8 == 0xF0: + w, value = 4, rune(octet&0x07) + } + for k := 1; k < w; k++ { + octet = emitter.buffer[pos+k] + value = (value << 6) + (rune(octet) & 0x3F) + } + pos += w + + // Write the character. + if value < 0x10000 { + var b [2]byte + b[high] = byte(value >> 8) + b[low] = byte(value & 0xFF) + emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1]) + } else { + // Write the character using a surrogate pair (check "reader.c"). + var b [4]byte + value -= 0x10000 + b[high] = byte(0xD8 + (value >> 18)) + b[low] = byte((value >> 10) & 0xFF) + b[high+2] = byte(0xDC + ((value >> 8) & 0xFF)) + b[low+2] = byte(value & 0xFF) + emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1], b[2], b[3]) + } + } + + // Write the raw buffer. + if err := emitter.write_handler(emitter, emitter.raw_buffer); err != nil { + return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) + } + emitter.buffer_pos = 0 + emitter.raw_buffer = emitter.raw_buffer[:0] + return true +} diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/yaml.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/yaml.go new file mode 100644 index 00000000..af4df8a4 --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/yaml.go @@ -0,0 +1,344 @@ +// Package yaml implements YAML support for the Go language. +// +// Source code and other details for the project are available at GitHub: +// +// https://github.com/go-yaml/yaml +// +package yaml + +import ( + "errors" + "fmt" + "reflect" + "strings" + "sync" +) + +// MapSlice encodes and decodes as a YAML map. +// The order of keys is preserved when encoding and decoding. +type MapSlice []MapItem + +// MapItem is an item in a MapSlice. +type MapItem struct { + Key, Value interface{} +} + +// The Unmarshaler interface may be implemented by types to customize their +// behavior when being unmarshaled from a YAML document. The UnmarshalYAML +// method receives a function that may be called to unmarshal the original +// YAML value into a field or variable. It is safe to call the unmarshal +// function parameter more than once if necessary. +type Unmarshaler interface { + UnmarshalYAML(unmarshal func(interface{}) error) error +} + +// The Marshaler interface may be implemented by types to customize their +// behavior when being marshaled into a YAML document. The returned value +// is marshaled in place of the original value implementing Marshaler. +// +// If an error is returned by MarshalYAML, the marshaling procedure stops +// and returns with the provided error. +type Marshaler interface { + MarshalYAML() (interface{}, error) +} + +// Unmarshal decodes the first document found within the in byte slice +// and assigns decoded values into the out value. +// +// Maps and pointers (to a struct, string, int, etc) are accepted as out +// values. If an internal pointer within a struct is not initialized, +// the yaml package will initialize it if necessary for unmarshalling +// the provided data. The out parameter must not be nil. +// +// The type of the decoded values should be compatible with the respective +// values in out. If one or more values cannot be decoded due to a type +// mismatches, decoding continues partially until the end of the YAML +// content, and a *yaml.TypeError is returned with details for all +// missed values. +// +// Struct fields are only unmarshalled if they are exported (have an +// upper case first letter), and are unmarshalled using the field name +// lowercased as the default key. Custom keys may be defined via the +// "yaml" name in the field tag: the content preceding the first comma +// is used as the key, and the following comma-separated options are +// used to tweak the marshalling process (see Marshal). +// Conflicting names result in a runtime error. +// +// For example: +// +// type T struct { +// F int `yaml:"a,omitempty"` +// B int +// } +// var t T +// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t) +// +// See the documentation of Marshal for the format of tags and a list of +// supported tag options. +// +func Unmarshal(in []byte, out interface{}) (err error) { + defer handleErr(&err) + d := newDecoder() + p := newParser(in) + defer p.destroy() + node := p.parse() + if node != nil { + v := reflect.ValueOf(out) + if v.Kind() == reflect.Ptr && !v.IsNil() { + v = v.Elem() + } + d.unmarshal(node, v) + } + if len(d.terrors) > 0 { + return &TypeError{d.terrors} + } + return nil +} + +// Marshal serializes the value provided into a YAML document. The structure +// of the generated document will reflect the structure of the value itself. +// Maps and pointers (to struct, string, int, etc) are accepted as the in value. +// +// Struct fields are only unmarshalled if they are exported (have an upper case +// first letter), and are unmarshalled using the field name lowercased as the +// default key. Custom keys may be defined via the "yaml" name in the field +// tag: the content preceding the first comma is used as the key, and the +// following comma-separated options are used to tweak the marshalling process. +// Conflicting names result in a runtime error. +// +// The field tag format accepted is: +// +// `(...) yaml:"[][,[,]]" (...)` +// +// The following flags are currently supported: +// +// omitempty Only include the field if it's not set to the zero +// value for the type or to empty slices or maps. +// Does not apply to zero valued structs. +// +// flow Marshal using a flow style (useful for structs, +// sequences and maps). +// +// inline Inline the field, which must be a struct or a map, +// causing all of its fields or keys to be processed as if +// they were part of the outer struct. For maps, keys must +// not conflict with the yaml keys of other struct fields. +// +// In addition, if the key is "-", the field is ignored. +// +// For example: +// +// type T struct { +// F int "a,omitempty" +// B int +// } +// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n" +// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n" +// +func Marshal(in interface{}) (out []byte, err error) { + defer handleErr(&err) + e := newEncoder() + defer e.destroy() + e.marshal("", reflect.ValueOf(in)) + e.finish() + out = e.out + return +} + +func handleErr(err *error) { + if v := recover(); v != nil { + if e, ok := v.(yamlError); ok { + *err = e.err + } else { + panic(v) + } + } +} + +type yamlError struct { + err error +} + +func fail(err error) { + panic(yamlError{err}) +} + +func failf(format string, args ...interface{}) { + panic(yamlError{fmt.Errorf("yaml: "+format, args...)}) +} + +// A TypeError is returned by Unmarshal when one or more fields in +// the YAML document cannot be properly decoded into the requested +// types. When this error is returned, the value is still +// unmarshaled partially. +type TypeError struct { + Errors []string +} + +func (e *TypeError) Error() string { + return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n ")) +} + +// -------------------------------------------------------------------------- +// Maintain a mapping of keys to structure field indexes + +// The code in this section was copied from mgo/bson. + +// structInfo holds details for the serialization of fields of +// a given struct. +type structInfo struct { + FieldsMap map[string]fieldInfo + FieldsList []fieldInfo + + // InlineMap is the number of the field in the struct that + // contains an ,inline map, or -1 if there's none. + InlineMap int +} + +type fieldInfo struct { + Key string + Num int + OmitEmpty bool + Flow bool + + // Inline holds the field index if the field is part of an inlined struct. + Inline []int +} + +var structMap = make(map[reflect.Type]*structInfo) +var fieldMapMutex sync.RWMutex + +func getStructInfo(st reflect.Type) (*structInfo, error) { + fieldMapMutex.RLock() + sinfo, found := structMap[st] + fieldMapMutex.RUnlock() + if found { + return sinfo, nil + } + + n := st.NumField() + fieldsMap := make(map[string]fieldInfo) + fieldsList := make([]fieldInfo, 0, n) + inlineMap := -1 + for i := 0; i != n; i++ { + field := st.Field(i) + if field.PkgPath != "" { + continue // Private field + } + + info := fieldInfo{Num: i} + + tag := field.Tag.Get("yaml") + if tag == "" && strings.Index(string(field.Tag), ":") < 0 { + tag = string(field.Tag) + } + if tag == "-" { + continue + } + + inline := false + fields := strings.Split(tag, ",") + if len(fields) > 1 { + for _, flag := range fields[1:] { + switch flag { + case "omitempty": + info.OmitEmpty = true + case "flow": + info.Flow = true + case "inline": + inline = true + default: + return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st)) + } + } + tag = fields[0] + } + + if inline { + switch field.Type.Kind() { + case reflect.Map: + if inlineMap >= 0 { + return nil, errors.New("Multiple ,inline maps in struct " + st.String()) + } + if field.Type.Key() != reflect.TypeOf("") { + return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String()) + } + inlineMap = info.Num + case reflect.Struct: + sinfo, err := getStructInfo(field.Type) + if err != nil { + return nil, err + } + for _, finfo := range sinfo.FieldsList { + if _, found := fieldsMap[finfo.Key]; found { + msg := "Duplicated key '" + finfo.Key + "' in struct " + st.String() + return nil, errors.New(msg) + } + if finfo.Inline == nil { + finfo.Inline = []int{i, finfo.Num} + } else { + finfo.Inline = append([]int{i}, finfo.Inline...) + } + fieldsMap[finfo.Key] = finfo + fieldsList = append(fieldsList, finfo) + } + default: + //return nil, errors.New("Option ,inline needs a struct value or map field") + return nil, errors.New("Option ,inline needs a struct value field") + } + continue + } + + if tag != "" { + info.Key = tag + } else { + info.Key = strings.ToLower(field.Name) + } + + if _, found = fieldsMap[info.Key]; found { + msg := "Duplicated key '" + info.Key + "' in struct " + st.String() + return nil, errors.New(msg) + } + + fieldsList = append(fieldsList, info) + fieldsMap[info.Key] = info + } + + sinfo = &structInfo{fieldsMap, fieldsList, inlineMap} + + fieldMapMutex.Lock() + structMap[st] = sinfo + fieldMapMutex.Unlock() + return sinfo, nil +} + +func isZero(v reflect.Value) bool { + switch v.Kind() { + case reflect.String: + return len(v.String()) == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + case reflect.Slice: + return v.Len() == 0 + case reflect.Map: + return v.Len() == 0 + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Struct: + vt := v.Type() + for i := v.NumField()-1; i >= 0; i-- { + if vt.Field(i).PkgPath != "" { + continue // Private field + } + if !isZero(v.Field(i)) { + return false + } + } + return true + } + return false +} diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/yamlh.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/yamlh.go new file mode 100644 index 00000000..d60a6b6b --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/yamlh.go @@ -0,0 +1,716 @@ +package yaml + +import ( + "io" +) + +// The version directive data. +type yaml_version_directive_t struct { + major int8 // The major version number. + minor int8 // The minor version number. +} + +// The tag directive data. +type yaml_tag_directive_t struct { + handle []byte // The tag handle. + prefix []byte // The tag prefix. +} + +type yaml_encoding_t int + +// The stream encoding. +const ( + // Let the parser choose the encoding. + yaml_ANY_ENCODING yaml_encoding_t = iota + + yaml_UTF8_ENCODING // The default UTF-8 encoding. + yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM. + yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM. +) + +type yaml_break_t int + +// Line break types. +const ( + // Let the parser choose the break type. + yaml_ANY_BREAK yaml_break_t = iota + + yaml_CR_BREAK // Use CR for line breaks (Mac style). + yaml_LN_BREAK // Use LN for line breaks (Unix style). + yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style). +) + +type yaml_error_type_t int + +// Many bad things could happen with the parser and emitter. +const ( + // No error is produced. + yaml_NO_ERROR yaml_error_type_t = iota + + yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory. + yaml_READER_ERROR // Cannot read or decode the input stream. + yaml_SCANNER_ERROR // Cannot scan the input stream. + yaml_PARSER_ERROR // Cannot parse the input stream. + yaml_COMPOSER_ERROR // Cannot compose a YAML document. + yaml_WRITER_ERROR // Cannot write to the output stream. + yaml_EMITTER_ERROR // Cannot emit a YAML stream. +) + +// The pointer position. +type yaml_mark_t struct { + index int // The position index. + line int // The position line. + column int // The position column. +} + +// Node Styles + +type yaml_style_t int8 + +type yaml_scalar_style_t yaml_style_t + +// Scalar styles. +const ( + // Let the emitter choose the style. + yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = iota + + yaml_PLAIN_SCALAR_STYLE // The plain scalar style. + yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style. + yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style. + yaml_LITERAL_SCALAR_STYLE // The literal scalar style. + yaml_FOLDED_SCALAR_STYLE // The folded scalar style. +) + +type yaml_sequence_style_t yaml_style_t + +// Sequence styles. +const ( + // Let the emitter choose the style. + yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota + + yaml_BLOCK_SEQUENCE_STYLE // The block sequence style. + yaml_FLOW_SEQUENCE_STYLE // The flow sequence style. +) + +type yaml_mapping_style_t yaml_style_t + +// Mapping styles. +const ( + // Let the emitter choose the style. + yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota + + yaml_BLOCK_MAPPING_STYLE // The block mapping style. + yaml_FLOW_MAPPING_STYLE // The flow mapping style. +) + +// Tokens + +type yaml_token_type_t int + +// Token types. +const ( + // An empty token. + yaml_NO_TOKEN yaml_token_type_t = iota + + yaml_STREAM_START_TOKEN // A STREAM-START token. + yaml_STREAM_END_TOKEN // A STREAM-END token. + + yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token. + yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token. + yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token. + yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token. + + yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token. + yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token. + yaml_BLOCK_END_TOKEN // A BLOCK-END token. + + yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token. + yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token. + yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token. + yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token. + + yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token. + yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token. + yaml_KEY_TOKEN // A KEY token. + yaml_VALUE_TOKEN // A VALUE token. + + yaml_ALIAS_TOKEN // An ALIAS token. + yaml_ANCHOR_TOKEN // An ANCHOR token. + yaml_TAG_TOKEN // A TAG token. + yaml_SCALAR_TOKEN // A SCALAR token. +) + +func (tt yaml_token_type_t) String() string { + switch tt { + case yaml_NO_TOKEN: + return "yaml_NO_TOKEN" + case yaml_STREAM_START_TOKEN: + return "yaml_STREAM_START_TOKEN" + case yaml_STREAM_END_TOKEN: + return "yaml_STREAM_END_TOKEN" + case yaml_VERSION_DIRECTIVE_TOKEN: + return "yaml_VERSION_DIRECTIVE_TOKEN" + case yaml_TAG_DIRECTIVE_TOKEN: + return "yaml_TAG_DIRECTIVE_TOKEN" + case yaml_DOCUMENT_START_TOKEN: + return "yaml_DOCUMENT_START_TOKEN" + case yaml_DOCUMENT_END_TOKEN: + return "yaml_DOCUMENT_END_TOKEN" + case yaml_BLOCK_SEQUENCE_START_TOKEN: + return "yaml_BLOCK_SEQUENCE_START_TOKEN" + case yaml_BLOCK_MAPPING_START_TOKEN: + return "yaml_BLOCK_MAPPING_START_TOKEN" + case yaml_BLOCK_END_TOKEN: + return "yaml_BLOCK_END_TOKEN" + case yaml_FLOW_SEQUENCE_START_TOKEN: + return "yaml_FLOW_SEQUENCE_START_TOKEN" + case yaml_FLOW_SEQUENCE_END_TOKEN: + return "yaml_FLOW_SEQUENCE_END_TOKEN" + case yaml_FLOW_MAPPING_START_TOKEN: + return "yaml_FLOW_MAPPING_START_TOKEN" + case yaml_FLOW_MAPPING_END_TOKEN: + return "yaml_FLOW_MAPPING_END_TOKEN" + case yaml_BLOCK_ENTRY_TOKEN: + return "yaml_BLOCK_ENTRY_TOKEN" + case yaml_FLOW_ENTRY_TOKEN: + return "yaml_FLOW_ENTRY_TOKEN" + case yaml_KEY_TOKEN: + return "yaml_KEY_TOKEN" + case yaml_VALUE_TOKEN: + return "yaml_VALUE_TOKEN" + case yaml_ALIAS_TOKEN: + return "yaml_ALIAS_TOKEN" + case yaml_ANCHOR_TOKEN: + return "yaml_ANCHOR_TOKEN" + case yaml_TAG_TOKEN: + return "yaml_TAG_TOKEN" + case yaml_SCALAR_TOKEN: + return "yaml_SCALAR_TOKEN" + } + return "" +} + +// The token structure. +type yaml_token_t struct { + // The token type. + typ yaml_token_type_t + + // The start/end of the token. + start_mark, end_mark yaml_mark_t + + // The stream encoding (for yaml_STREAM_START_TOKEN). + encoding yaml_encoding_t + + // The alias/anchor/scalar value or tag/tag directive handle + // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN). + value []byte + + // The tag suffix (for yaml_TAG_TOKEN). + suffix []byte + + // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN). + prefix []byte + + // The scalar style (for yaml_SCALAR_TOKEN). + style yaml_scalar_style_t + + // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN). + major, minor int8 +} + +// Events + +type yaml_event_type_t int8 + +// Event types. +const ( + // An empty event. + yaml_NO_EVENT yaml_event_type_t = iota + + yaml_STREAM_START_EVENT // A STREAM-START event. + yaml_STREAM_END_EVENT // A STREAM-END event. + yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event. + yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event. + yaml_ALIAS_EVENT // An ALIAS event. + yaml_SCALAR_EVENT // A SCALAR event. + yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event. + yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event. + yaml_MAPPING_START_EVENT // A MAPPING-START event. + yaml_MAPPING_END_EVENT // A MAPPING-END event. +) + +// The event structure. +type yaml_event_t struct { + + // The event type. + typ yaml_event_type_t + + // The start and end of the event. + start_mark, end_mark yaml_mark_t + + // The document encoding (for yaml_STREAM_START_EVENT). + encoding yaml_encoding_t + + // The version directive (for yaml_DOCUMENT_START_EVENT). + version_directive *yaml_version_directive_t + + // The list of tag directives (for yaml_DOCUMENT_START_EVENT). + tag_directives []yaml_tag_directive_t + + // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT). + anchor []byte + + // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). + tag []byte + + // The scalar value (for yaml_SCALAR_EVENT). + value []byte + + // Is the document start/end indicator implicit, or the tag optional? + // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT). + implicit bool + + // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT). + quoted_implicit bool + + // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). + style yaml_style_t +} + +func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) } +func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) } +func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) } + +// Nodes + +const ( + yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null. + yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false. + yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values. + yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values. + yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values. + yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values. + + yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences. + yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping. + + // Not in original libyaml. + yaml_BINARY_TAG = "tag:yaml.org,2002:binary" + yaml_MERGE_TAG = "tag:yaml.org,2002:merge" + + yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str. + yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq. + yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map. +) + +type yaml_node_type_t int + +// Node types. +const ( + // An empty node. + yaml_NO_NODE yaml_node_type_t = iota + + yaml_SCALAR_NODE // A scalar node. + yaml_SEQUENCE_NODE // A sequence node. + yaml_MAPPING_NODE // A mapping node. +) + +// An element of a sequence node. +type yaml_node_item_t int + +// An element of a mapping node. +type yaml_node_pair_t struct { + key int // The key of the element. + value int // The value of the element. +} + +// The node structure. +type yaml_node_t struct { + typ yaml_node_type_t // The node type. + tag []byte // The node tag. + + // The node data. + + // The scalar parameters (for yaml_SCALAR_NODE). + scalar struct { + value []byte // The scalar value. + length int // The length of the scalar value. + style yaml_scalar_style_t // The scalar style. + } + + // The sequence parameters (for YAML_SEQUENCE_NODE). + sequence struct { + items_data []yaml_node_item_t // The stack of sequence items. + style yaml_sequence_style_t // The sequence style. + } + + // The mapping parameters (for yaml_MAPPING_NODE). + mapping struct { + pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value). + pairs_start *yaml_node_pair_t // The beginning of the stack. + pairs_end *yaml_node_pair_t // The end of the stack. + pairs_top *yaml_node_pair_t // The top of the stack. + style yaml_mapping_style_t // The mapping style. + } + + start_mark yaml_mark_t // The beginning of the node. + end_mark yaml_mark_t // The end of the node. + +} + +// The document structure. +type yaml_document_t struct { + + // The document nodes. + nodes []yaml_node_t + + // The version directive. + version_directive *yaml_version_directive_t + + // The list of tag directives. + tag_directives_data []yaml_tag_directive_t + tag_directives_start int // The beginning of the tag directives list. + tag_directives_end int // The end of the tag directives list. + + start_implicit int // Is the document start indicator implicit? + end_implicit int // Is the document end indicator implicit? + + // The start/end of the document. + start_mark, end_mark yaml_mark_t +} + +// The prototype of a read handler. +// +// The read handler is called when the parser needs to read more bytes from the +// source. The handler should write not more than size bytes to the buffer. +// The number of written bytes should be set to the size_read variable. +// +// [in,out] data A pointer to an application data specified by +// yaml_parser_set_input(). +// [out] buffer The buffer to write the data from the source. +// [in] size The size of the buffer. +// [out] size_read The actual number of bytes read from the source. +// +// On success, the handler should return 1. If the handler failed, +// the returned value should be 0. On EOF, the handler should set the +// size_read to 0 and return 1. +type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error) + +// This structure holds information about a potential simple key. +type yaml_simple_key_t struct { + possible bool // Is a simple key possible? + required bool // Is a simple key required? + token_number int // The number of the token. + mark yaml_mark_t // The position mark. +} + +// The states of the parser. +type yaml_parser_state_t int + +const ( + yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota + + yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document. + yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START. + yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document. + yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END. + yaml_PARSE_BLOCK_NODE_STATE // Expect a block node. + yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence. + yaml_PARSE_FLOW_NODE_STATE // Expect a flow node. + yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence. + yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence. + yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence. + yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. + yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key. + yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value. + yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry. + yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. + yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. + yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. + yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping. + yaml_PARSE_END_STATE // Expect nothing. +) + +func (ps yaml_parser_state_t) String() string { + switch ps { + case yaml_PARSE_STREAM_START_STATE: + return "yaml_PARSE_STREAM_START_STATE" + case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: + return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE" + case yaml_PARSE_DOCUMENT_START_STATE: + return "yaml_PARSE_DOCUMENT_START_STATE" + case yaml_PARSE_DOCUMENT_CONTENT_STATE: + return "yaml_PARSE_DOCUMENT_CONTENT_STATE" + case yaml_PARSE_DOCUMENT_END_STATE: + return "yaml_PARSE_DOCUMENT_END_STATE" + case yaml_PARSE_BLOCK_NODE_STATE: + return "yaml_PARSE_BLOCK_NODE_STATE" + case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: + return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE" + case yaml_PARSE_FLOW_NODE_STATE: + return "yaml_PARSE_FLOW_NODE_STATE" + case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: + return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE" + case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: + return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE" + case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: + return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE" + case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: + return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE" + case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: + return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE" + case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: + return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE" + case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE" + case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: + return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE" + case yaml_PARSE_FLOW_MAPPING_KEY_STATE: + return "yaml_PARSE_FLOW_MAPPING_KEY_STATE" + case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: + return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE" + case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: + return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE" + case yaml_PARSE_END_STATE: + return "yaml_PARSE_END_STATE" + } + return "" +} + +// This structure holds aliases data. +type yaml_alias_data_t struct { + anchor []byte // The anchor. + index int // The node id. + mark yaml_mark_t // The anchor mark. +} + +// The parser structure. +// +// All members are internal. Manage the structure using the +// yaml_parser_ family of functions. +type yaml_parser_t struct { + + // Error handling + + error yaml_error_type_t // Error type. + + problem string // Error description. + + // The byte about which the problem occured. + problem_offset int + problem_value int + problem_mark yaml_mark_t + + // The error context. + context string + context_mark yaml_mark_t + + // Reader stuff + + read_handler yaml_read_handler_t // Read handler. + + input_file io.Reader // File input data. + input []byte // String input data. + input_pos int + + eof bool // EOF flag + + buffer []byte // The working buffer. + buffer_pos int // The current position of the buffer. + + unread int // The number of unread characters in the buffer. + + raw_buffer []byte // The raw buffer. + raw_buffer_pos int // The current position of the buffer. + + encoding yaml_encoding_t // The input encoding. + + offset int // The offset of the current position (in bytes). + mark yaml_mark_t // The mark of the current position. + + // Scanner stuff + + stream_start_produced bool // Have we started to scan the input stream? + stream_end_produced bool // Have we reached the end of the input stream? + + flow_level int // The number of unclosed '[' and '{' indicators. + + tokens []yaml_token_t // The tokens queue. + tokens_head int // The head of the tokens queue. + tokens_parsed int // The number of tokens fetched from the queue. + token_available bool // Does the tokens queue contain a token ready for dequeueing. + + indent int // The current indentation level. + indents []int // The indentation levels stack. + + simple_key_allowed bool // May a simple key occur at the current position? + simple_keys []yaml_simple_key_t // The stack of simple keys. + + // Parser stuff + + state yaml_parser_state_t // The current parser state. + states []yaml_parser_state_t // The parser states stack. + marks []yaml_mark_t // The stack of marks. + tag_directives []yaml_tag_directive_t // The list of TAG directives. + + // Dumper stuff + + aliases []yaml_alias_data_t // The alias data. + + document *yaml_document_t // The currently parsed document. +} + +// Emitter Definitions + +// The prototype of a write handler. +// +// The write handler is called when the emitter needs to flush the accumulated +// characters to the output. The handler should write @a size bytes of the +// @a buffer to the output. +// +// @param[in,out] data A pointer to an application data specified by +// yaml_emitter_set_output(). +// @param[in] buffer The buffer with bytes to be written. +// @param[in] size The size of the buffer. +// +// @returns On success, the handler should return @c 1. If the handler failed, +// the returned value should be @c 0. +// +type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error + +type yaml_emitter_state_t int + +// The emitter states. +const ( + // Expect STREAM-START. + yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota + + yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END. + yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END. + yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document. + yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END. + yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence. + yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence. + yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. + yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. + yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping. + yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. + yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence. + yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence. + yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. + yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping. + yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping. + yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping. + yaml_EMIT_END_STATE // Expect nothing. +) + +// The emitter structure. +// +// All members are internal. Manage the structure using the @c yaml_emitter_ +// family of functions. +type yaml_emitter_t struct { + + // Error handling + + error yaml_error_type_t // Error type. + problem string // Error description. + + // Writer stuff + + write_handler yaml_write_handler_t // Write handler. + + output_buffer *[]byte // String output data. + output_file io.Writer // File output data. + + buffer []byte // The working buffer. + buffer_pos int // The current position of the buffer. + + raw_buffer []byte // The raw buffer. + raw_buffer_pos int // The current position of the buffer. + + encoding yaml_encoding_t // The stream encoding. + + // Emitter stuff + + canonical bool // If the output is in the canonical style? + best_indent int // The number of indentation spaces. + best_width int // The preferred width of the output lines. + unicode bool // Allow unescaped non-ASCII characters? + line_break yaml_break_t // The preferred line break. + + state yaml_emitter_state_t // The current emitter state. + states []yaml_emitter_state_t // The stack of states. + + events []yaml_event_t // The event queue. + events_head int // The head of the event queue. + + indents []int // The stack of indentation levels. + + tag_directives []yaml_tag_directive_t // The list of tag directives. + + indent int // The current indentation level. + + flow_level int // The current flow level. + + root_context bool // Is it the document root context? + sequence_context bool // Is it a sequence context? + mapping_context bool // Is it a mapping context? + simple_key_context bool // Is it a simple mapping key context? + + line int // The current line. + column int // The current column. + whitespace bool // If the last character was a whitespace? + indention bool // If the last character was an indentation character (' ', '-', '?', ':')? + open_ended bool // If an explicit document end is required? + + // Anchor analysis. + anchor_data struct { + anchor []byte // The anchor value. + alias bool // Is it an alias? + } + + // Tag analysis. + tag_data struct { + handle []byte // The tag handle. + suffix []byte // The tag suffix. + } + + // Scalar analysis. + scalar_data struct { + value []byte // The scalar value. + multiline bool // Does the scalar contain line breaks? + flow_plain_allowed bool // Can the scalar be expessed in the flow plain style? + block_plain_allowed bool // Can the scalar be expressed in the block plain style? + single_quoted_allowed bool // Can the scalar be expressed in the single quoted style? + block_allowed bool // Can the scalar be expressed in the literal or folded styles? + style yaml_scalar_style_t // The output style. + } + + // Dumper stuff + + opened bool // If the stream was already opened? + closed bool // If the stream was already closed? + + // The information associated with the document nodes. + anchors *struct { + references int // The number of references. + anchor int // The anchor id. + serialized bool // If the node has been emitted? + } + + last_anchor_id int // The last assigned anchor id. + + document *yaml_document_t // The currently emitted document. +} diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/yamlprivateh.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/yamlprivateh.go new file mode 100644 index 00000000..8110ce3c --- /dev/null +++ b/Godeps/_workspace/src/gopkg.in/yaml.v2/yamlprivateh.go @@ -0,0 +1,173 @@ +package yaml + +const ( + // The size of the input raw buffer. + input_raw_buffer_size = 512 + + // The size of the input buffer. + // It should be possible to decode the whole raw buffer. + input_buffer_size = input_raw_buffer_size * 3 + + // The size of the output buffer. + output_buffer_size = 128 + + // The size of the output raw buffer. + // It should be possible to encode the whole output buffer. + output_raw_buffer_size = (output_buffer_size*2 + 2) + + // The size of other stacks and queues. + initial_stack_size = 16 + initial_queue_size = 16 + initial_string_size = 16 +) + +// Check if the character at the specified position is an alphabetical +// character, a digit, '_', or '-'. +func is_alpha(b []byte, i int) bool { + return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' +} + +// Check if the character at the specified position is a digit. +func is_digit(b []byte, i int) bool { + return b[i] >= '0' && b[i] <= '9' +} + +// Get the value of a digit. +func as_digit(b []byte, i int) int { + return int(b[i]) - '0' +} + +// Check if the character at the specified position is a hex-digit. +func is_hex(b []byte, i int) bool { + return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' +} + +// Get the value of a hex-digit. +func as_hex(b []byte, i int) int { + bi := b[i] + if bi >= 'A' && bi <= 'F' { + return int(bi) - 'A' + 10 + } + if bi >= 'a' && bi <= 'f' { + return int(bi) - 'a' + 10 + } + return int(bi) - '0' +} + +// Check if the character is ASCII. +func is_ascii(b []byte, i int) bool { + return b[i] <= 0x7F +} + +// Check if the character at the start of the buffer can be printed unescaped. +func is_printable(b []byte, i int) bool { + return ((b[i] == 0x0A) || // . == #x0A + (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E + (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF + (b[i] > 0xC2 && b[i] < 0xED) || + (b[i] == 0xED && b[i+1] < 0xA0) || + (b[i] == 0xEE) || + (b[i] == 0xEF && // #xE000 <= . <= #xFFFD + !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF + !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) +} + +// Check if the character at the specified position is NUL. +func is_z(b []byte, i int) bool { + return b[i] == 0x00 +} + +// Check if the beginning of the buffer is a BOM. +func is_bom(b []byte, i int) bool { + return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF +} + +// Check if the character at the specified position is space. +func is_space(b []byte, i int) bool { + return b[i] == ' ' +} + +// Check if the character at the specified position is tab. +func is_tab(b []byte, i int) bool { + return b[i] == '\t' +} + +// Check if the character at the specified position is blank (space or tab). +func is_blank(b []byte, i int) bool { + //return is_space(b, i) || is_tab(b, i) + return b[i] == ' ' || b[i] == '\t' +} + +// Check if the character at the specified position is a line break. +func is_break(b []byte, i int) bool { + return (b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) +} + +func is_crlf(b []byte, i int) bool { + return b[i] == '\r' && b[i+1] == '\n' +} + +// Check if the character is a line break or NUL. +func is_breakz(b []byte, i int) bool { + //return is_break(b, i) || is_z(b, i) + return ( // is_break: + b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) + // is_z: + b[i] == 0) +} + +// Check if the character is a line break, space, or NUL. +func is_spacez(b []byte, i int) bool { + //return is_space(b, i) || is_breakz(b, i) + return ( // is_space: + b[i] == ' ' || + // is_breakz: + b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) + b[i] == 0) +} + +// Check if the character is a line break, space, tab, or NUL. +func is_blankz(b []byte, i int) bool { + //return is_blank(b, i) || is_breakz(b, i) + return ( // is_blank: + b[i] == ' ' || b[i] == '\t' || + // is_breakz: + b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) + b[i] == 0) +} + +// Determine the width of the character. +func width(b byte) int { + // Don't replace these by a switch without first + // confirming that it is being inlined. + if b&0x80 == 0x00 { + return 1 + } + if b&0xE0 == 0xC0 { + return 2 + } + if b&0xF0 == 0xE0 { + return 3 + } + if b&0xF8 == 0xF0 { + return 4 + } + return 0 + +} diff --git a/assets/bindata.go b/assets/bindata.go new file mode 100644 index 00000000..9312b036 --- /dev/null +++ b/assets/bindata.go @@ -0,0 +1,384 @@ +package assets + +import ( + "fmt" + "reflect" + "strings" + "unsafe" + "os" + "time" + "io/ioutil" + "path" + "path/filepath" +) + +func bindata_read(data, name string) ([]byte, error) { + var empty [0]byte + sx := (*reflect.StringHeader)(unsafe.Pointer(&data)) + b := empty[:] + bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + bx.Data = sx.Data + bx.Len = len(data) + bx.Cap = bx.Len + return b, nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindata_file_info struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +func (fi bindata_file_info) Name() string { + return fi.name +} +func (fi bindata_file_info) Size() int64 { + return fi.size +} +func (fi bindata_file_info) Mode() os.FileMode { + return fi.mode +} +func (fi bindata_file_info) ModTime() time.Time { + return fi.modTime +} +func (fi bindata_file_info) IsDir() bool { + return false +} +func (fi bindata_file_info) Sys() interface{} { + return nil +} + +var _bundle_css_gz = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\xad\x58\x6d\x6f\xe3\x36\x0c\xfe\x2b\xd9\x15\x43\xaf\x87\x38\x73\x92\xa6\x2f\x36\x6e\x2f\xbd\xa2\xdf\xf6\x69\x1f\x6f\x1d\x20\xdb\x4a\xa2\x55\xb6\x0c\x49\x6e\x9b\x33\xf2\xdf\x47\x49\x96\x2d\x39\x72\x7b\x1b\xd6\x00\xad\x23\x51\x24\xf5\x90\x7c\x48\x37\x6b\xa4\x64\xd5\x9c\x54\x75\x23\xdb\x8c\xf1\x02\xf3\xa4\x62\x15\x4e\x59\x23\x29\xa9\x70\x12\x1f\x3f\xcd\xc9\xd7\x9c\x22\x21\x3e\x7d\xfe\x30\x23\x39\xab\xa2\x0f\x8f\x49\x86\xb7\x8c\x63\xbb\xf3\xd7\x67\xbd\x6e\x97\xdb\x12\xf1\x1d\xa9\xe0\xec\x22\xdf\x23\x19\x49\x22\x29\x9e\x77\xcf\xac\x26\xf9\x7c\x51\x62\x21\xd0\x0e\xb7\x2f\x7b\x22\x71\x24\x6a\x94\x63\xb0\xfb\xc2\x51\x7d\xfc\x75\xcb\x2a\x19\x6d\x61\xa5\xed\x9e\x4a\x42\x0f\x89\x7a\xc6\x94\xb2\x54\xf0\x3c\x69\x38\xfd\xa8\x16\x7e\xb2\xab\x0b\xcc\xe4\x2f\xd7\xeb\x4b\xf8\xb9\xbd\xba\xf8\x0e\x99\x33\x82\xb7\xe4\xf5\x02\xdc\x2d\x91\xfc\x78\x8e\xcb\x0c\x17\x05\x2e\x22\x56\xe3\x4a\x1e\x6a\x7c\x7e\x31\x3f\x55\xf0\xc2\xb6\xdb\xc1\x8a\x3d\xab\x56\x83\xe2\x52\x06\xa4\x25\x6f\xf0\xa4\x01\xf1\xbc\x1b\x3c\xb4\xab\xfd\x51\xd8\x3d\xbf\x48\x35\x28\x2f\x98\xec\xf6\x32\xb9\x8c\x63\xf3\x5d\xc8\x03\x55\x08\x82\x20\x3d\x4e\x86\x2b\x1c\xad\x20\xca\x27\x5a\x4f\xec\x8a\x1a\xa3\x27\x93\x2c\x05\x11\x35\x45\x87\x84\x54\x2a\x67\xa2\x8c\xb2\xfc\x29\x95\xf8\x55\x46\x05\xce\x19\x47\x92\xb0\x0a\x36\xf7\x98\x13\x99\xbe\x90\x42\xee\x93\x25\x2e\x53\x93\x26\x11\xd7\x2a\x17\x2b\x58\xd1\x67\x10\x25\xbb\x2a\xc9\x21\x0e\x98\x1b\xab\xcf\x88\x13\x54\x49\xeb\x89\x96\x92\x1c\x55\x42\x21\x63\x5c\xd0\x86\xf7\xc6\x3b\x47\x37\xc5\x5b\xa3\xfa\xb8\xd0\x97\xce\xd9\xce\x5e\x3b\x57\x57\x05\xa5\xe7\x7f\xe2\x9b\x38\x3e\xef\x04\xe0\xf2\xa4\x16\x44\x04\xa5\x96\x56\x4a\x60\xc4\xf3\x7d\x50\x66\x65\x65\x1a\x01\xb5\x14\x92\x58\xbb\x12\x61\x43\x97\x56\x84\xb2\x1d\x54\x62\x50\x66\x63\x65\x4a\x5c\x35\x41\x89\x2b\x2b\x51\xd3\x26\x6c\xe7\xda\x4a\xe4\xa8\xca\x31\x0d\xca\xdc\x9c\x1f\x3f\xb5\x35\x2a\x0a\x52\xed\x92\x38\xcd\xd8\x6b\x24\xc8\x37\xf5\xc5\xf0\x45\x04\x2b\xc7\x8c\x15\x07\x2f\x91\xee\x39\x23\xc5\xec\x0f\x88\xd1\xec\x77\x56\xb1\x79\x09\xbf\x74\x99\xa7\x19\xca\x9f\x76\x9c\x35\x55\x91\x9c\x6d\x63\xf5\x39\x1a\xfa\x51\xc7\x93\xe5\x55\xfd\x3a\x9b\x3c\x7c\xcc\x34\x5f\x39\xa2\xb0\x2f\x01\x46\xc8\xb1\xb9\x00\x79\x88\x0c\x27\xdb\x34\x6f\xb8\x60\x3c\xa9\x19\x51\x49\x74\xac\x5b\x2f\x3d\x16\x9b\xe3\x42\xa2\x8c\x12\x21\xdb\x9a\x09\xa2\xd3\x13\xd8\x00\x17\xa9\xce\x97\x38\x05\x96\xd2\x57\x05\x63\x25\x3c\x98\x94\x5d\xc5\x71\xfd\xea\xb9\xbf\x5a\xad\xd2\x9c\x51\xb0\x74\xf6\xf0\xf0\x90\xba\xf7\x0f\xfa\xa5\xcd\x46\x0a\x5d\x04\xfe\xf0\xc1\x38\xca\x04\xa3\x8d\xc4\xda\xf0\x46\x9b\x31\xb6\xf5\x73\x57\x31\x71\xfc\x63\xca\x9e\x31\xdf\x52\xf6\x92\xa0\x46\x32\xa0\x57\x56\x55\x38\x97\xf3\x85\x20\x05\xd4\x9d\x06\x47\x8c\xef\x64\xaf\xd1\x5f\x7a\x56\xf7\xf1\x5c\x03\x84\xcb\x0d\xd8\x18\x21\x36\x88\x26\x40\x19\x32\xca\xf7\x84\x16\x1d\xaf\x47\x9d\xc2\x25\xf8\xe6\x0a\xee\x95\x73\xad\x8b\xcf\x72\xb9\x74\x04\x16\x02\x53\x70\x16\x17\xd6\xba\xa9\xce\xa5\xb9\xae\x4e\x25\xbd\x00\xee\xcc\x00\x0e\xc8\x80\xb3\xab\xbb\xbb\xeb\xcd\x8d\x81\x0d\x10\x54\xfa\x3b\xbc\x6f\x6f\x6f\x6d\x8d\x2b\xcc\x94\x92\x1f\x48\x59\x33\x2e\x81\x28\x8e\x0b\x03\x45\xd4\xe1\xd3\x3a\x08\x76\x49\xb0\x19\xc7\xd2\x98\x72\xc2\x39\x56\x12\xb8\xdf\xf5\xdd\xdd\xc3\xd5\x6f\x27\x82\x28\x97\xe4\x19\xb7\xa7\xda\x8f\x7e\x9c\x5c\x57\xdc\x14\x3b\x61\x41\xff\xdc\x8c\xb4\x41\xc2\x75\x90\x31\xda\x36\x70\x5d\x37\xf1\xb5\x21\x3f\xd0\x1d\xcf\x93\x6f\x18\x6c\x0f\x71\xd0\x90\x0e\x61\x58\xde\xab\xcf\xd8\x0b\x20\x5e\xf9\x11\x72\x8c\xdb\xfc\xb8\x68\xdd\x30\x06\xce\x77\x38\x51\x8c\x9e\x61\x1e\x50\xf4\xa7\x32\x63\x78\x8a\x32\xc4\xa7\x74\xdc\xdf\x9f\x3a\x60\x22\xd2\xdd\xfb\xcb\x97\x2f\x5e\x40\xad\x51\x9b\x03\x16\x33\xe8\x61\xd9\x13\x91\x8a\xb6\xd2\xf1\xda\x96\x62\x67\xb1\x14\x7a\xc1\x15\xd4\x02\x8e\x86\x08\x58\xe9\xc9\xf6\x2a\xbb\xfe\x77\x23\x24\xd9\x1e\x22\x4b\xa3\x76\xbb\xd3\xe7\x9d\x99\x92\x75\x4c\x78\xfd\xd0\x6e\xe8\xc5\x08\x86\xa7\x52\x9c\xe8\xf7\x0e\x04\x04\x0d\xbb\x69\x80\x4d\xc2\x99\x0e\x1c\xf7\x58\x45\xaa\xaf\xce\xf6\x4b\xc3\xb3\xeb\xd5\x24\xcf\x8e\x08\x61\x13\x4e\xde\x61\x08\x54\x01\x1e\x85\xdb\xab\x47\xdb\x50\x8c\x3a\x2f\xf8\xd6\xeb\x71\x3e\x7f\x07\xe9\x7a\xb7\x32\xbd\xc6\xc6\xd3\x54\x4e\x37\xaf\x2a\xe2\x89\x53\x4b\x8d\x0e\x2f\xe9\x11\x23\xa4\xe7\xab\x9a\xe4\x3e\x8b\x26\x2b\x89\x7c\x9c\x4f\x0a\x28\x4c\x1e\x5b\xa7\xc4\xdf\xd5\xd5\xfe\xab\x2b\xbe\x4d\x64\x27\xdc\xfe\x8e\xed\x37\x88\xee\xbd\x93\x6f\x30\xdf\xd4\xd1\x7c\x8f\xf3\x27\x48\xf3\xc7\x30\xa9\x79\x33\xa2\xca\x2f\x70\x4d\x92\x1c\xd1\x2e\xc7\x4a\x52\x14\xf4\x24\x36\x2d\xf4\x48\x24\x13\x7d\x6a\xcc\x78\x0e\x4d\xba\xa1\x9e\x6d\x2c\xd2\x86\x0d\x2f\x4f\xa3\xe4\xf3\x4d\x1c\x8f\x0b\x86\xa2\x0c\xd3\xf0\x35\x3c\x4b\xb1\xf5\x61\xbd\x5e\x8f\xab\x23\x38\x90\x78\x55\x9a\xfa\xdd\x53\xb9\xfd\xff\x51\x9b\xdf\x0e\x3a\xe7\x6a\x4e\x9e\x91\xc4\x33\xaf\x70\xbb\xf7\x39\xd3\x95\x67\xee\x58\x3c\xda\xf1\x0f\x19\x91\x1e\xa4\xae\xb0\x94\x3c\xfc\x02\x2c\xe9\x6c\x0c\x88\xb9\xb6\x2d\x1b\x6f\x0f\x02\xdd\x0f\xa6\xe1\x31\xc6\xed\x38\x81\xbc\xd6\x4d\x65\xd0\xd9\x9e\xc4\xbf\x7f\x65\x8d\xd4\xbb\x69\xeb\xd2\xb2\xc2\x2b\x59\xa6\x2e\xbe\xea\x6b\x87\x2c\x3c\x76\x7f\xfa\x80\x72\x4c\x91\x2a\x0f\x4b\x37\xc6\x65\xd7\x48\x60\x20\x74\x26\x97\x8e\x16\xa3\x4b\x2f\x51\xd5\x14\xec\xe6\x74\x3f\x21\xee\xa1\x32\x70\x65\xf8\xb8\x5f\xb4\xaf\x37\xae\xd5\x19\x72\x87\xaa\xf1\x6b\x9b\x13\xa1\x4e\xba\xc3\x71\x2c\x08\x80\xaa\x40\x2b\x69\x8f\xe0\x47\x09\x6d\xb3\xf8\xcd\x81\x27\xf5\xc3\xea\x6b\x84\xa8\x7b\xac\xb0\x56\x02\x5d\x5e\x4d\x57\x4f\x70\xb2\x76\x72\x2b\xfd\x16\x11\xb8\xc1\x6b\xb2\x0a\xbd\xa1\x8c\x0a\xa1\xb3\xd6\xf7\x4d\xf3\x3d\x32\xbd\xc5\x09\x59\x5f\xf6\x9b\x77\xba\x5b\xaf\x82\x63\xd1\x50\x29\xbe\xe3\xd5\x20\x9e\x7c\x2f\xf0\xd9\xc6\x00\xd8\xfd\xc3\x05\x12\xf7\xbf\x61\x14\xf7\xf8\x2c\xc7\xf5\xea\xa8\xf6\x6a\x75\x58\xff\xb9\x20\xcf\xed\x89\x53\xbd\xd3\xd1\x41\xbb\xed\xce\xef\xdd\x59\x30\xb9\x65\x4e\x76\x0e\x1b\xaa\xd3\xc0\x8b\x60\xdf\xe5\xae\xae\x6e\x6f\x86\x5d\x49\x4a\x1c\x3c\x26\xb0\xca\x52\xbb\x65\x5b\xe5\x88\x34\x06\xe3\x10\x4e\x53\xf8\xd3\x98\xf5\xd1\xb0\x38\xb9\x9d\xdb\xc1\xcc\x53\x1a\x78\x21\x99\xcc\x97\xd1\x2c\xae\x93\xc5\x96\xc3\xd8\xaf\x37\x03\xe8\xcd\x1f\x56\x83\x0e\xcd\x64\x20\x46\x7d\x6b\x38\xe6\xbc\x42\x4e\x30\xef\x20\x39\xc1\xbb\xff\x00\x01\x9c\x3a\x2f\x7b\x14\x00\x00" + +func bundle_css_gz_bytes() ([]byte, error) { + return bindata_read( + _bundle_css_gz, + "bundle.css.gz", + ) +} + +func bundle_css_gz() (*asset, error) { + bytes, err := bundle_css_gz_bytes() + if err != nil { + return nil, err + } + + info := bindata_file_info{name: "bundle.css.gz", size: 1544, mode: os.FileMode(436), modTime: time.Unix(1432518658, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _bundle_js_gz = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\xd4\xbd\xd9\x62\xdb\xc6\x92\x00\xfa\x3e\x5f\x21\x71\x32\x0c\x10\x42\x14\x29\xdb\x59\x40\x83\x3c\x8e\x2d\xc7\x4e\xbc\xc5\x5b\xe2\xd0\x3c\x1a\x88\x6c\x4a\xb0\x40\x80\x06\x40\xc9\xb2\xc0\xfb\xed\xb7\xaa\x7a\x07\x40\x4a\x76\x32\x33\xf7\x3e\xd8\x22\x80\x5e\xaa\xab\xab\x6b\xeb\xea\xea\xdd\xf9\x2a\x99\x16\x51\x9a\xec\x14\x0e\xf3\x12\x2f\x73\xaf\xd4\x9b\xc8\x09\xbd\xdc\xbd\x8a\xe6\xce\x6e\x32\x0e\x27\xfc\x17\xa3\x5f\xe7\x61\xb6\xb3\x0a\x5a\xb2\x68\x2b\x08\x8a\xcb\x25\x4b\xe7\x3b\x19\xfb\xb8\x8a\x32\xd6\x6e\x8b\x1f\x03\xac\x93\xb7\xdb\x2b\x37\x63\xc5\x2a\x4b\x76\x56\xd0\xe8\x6e\xcf\xc5\xf7\xa9\x7c\x97\x8a\x77\xd8\xea\x34\x48\xd8\xc5\xce\x61\x96\xa5\x99\xd3\xba\x1f\x26\x49\x5a\xec\xcc\xa3\x64\xb6\xb3\x48\x67\xab\x98\xed\x7c\xdb\xea\x84\x9d\xd6\xb7\x2d\x77\x50\x9c\x66\xe9\xc5\xce\xb4\x3b\x4d\x67\x2c\x68\x3d\x7d\xfe\xe0\xcd\x93\xc3\xa3\x67\xcf\x5f\x1f\x3d\x7c\xfe\xe6\xd9\x83\x96\x37\x5d\x63\x7b\x71\x80\xb0\x07\x57\xec\xd3\x32\xcd\x8a\xdc\xbf\x5a\xaf\x07\x38\x86\x71\x6f\xd2\x9d\x86\x71\xec\xc4\x5d\xf1\xc9\x93\xa3\x71\x0a\x3e\xc0\x24\xa0\x82\xfd\xc9\xb8\x98\x0c\x04\xa8\x91\x93\x8c\x12\xbf\x70\xd7\x5e\xec\xe9\x9a\x85\xc7\x71\xb7\x16\xa5\xb0\x4b\xf9\x71\x3d\x87\x91\x60\x73\xe9\x4d\xf0\xe5\x85\x41\x6f\x10\xde\xcd\xba\x31\x4b\x4e\x8a\xd3\x41\xd8\xe9\xb8\x91\x93\x21\xd2\x15\x08\x6b\xe7\xaa\xef\x8f\x35\xb4\xd8\xb9\x7b\xd5\x5a\xe5\x6c\x27\x2f\xb2\x68\x5a\xb4\x08\x93\x59\x50\x38\xad\x8c\x85\xf0\xec\x7a\x91\x7a\xd8\xcb\xd2\x55\xc1\x32\x78\x97\x06\x51\xf7\x25\x3e\x40\xa7\x51\xf7\x01\x9b\x87\xab\xb8\xa0\x17\x03\x28\xdc\xdd\x8f\xb2\x29\x94\xa2\x9f\xd3\x74\xb1\x08\x93\x59\x8b\xcf\x51\x1e\xd0\xcb\x3c\x9d\x9e\x31\x6c\x7c\xc5\x9f\x57\x45\x14\xc3\xd3\x34\x90\x55\x96\x69\xc2\x92\x22\xdf\xbf\xb7\x5c\x76\x3f\xe4\x9f\xe0\x5b\x5c\xfb\x76\x3f\x4d\x12\x36\x2d\xc4\xf7\x65\xfd\xfb\x69\x28\x3f\xce\x6b\x1f\x5f\xb1\xa2\x88\x92\x93\x5c\x14\x38\xe5\x05\x42\xc2\x4b\xbe\x4f\x03\x85\xd7\xb3\x20\x4e\x61\xaa\x5f\x15\x69\x16\x9e\xb0\xee\x6a\x15\xcd\x06\xb3\xb2\x74\x4e\xbb\x49\x78\x1e\x9d\x84\x05\x73\x5a\x53\x0e\x46\x0b\xe9\xd0\xab\x15\x0f\x66\xc1\xaa\xfb\xe6\xcd\xe3\x07\x8e\xeb\x7a\x79\x17\x90\xae\x2b\xa8\x79\x70\xaf\xc4\x04\xe5\xdd\x9c\x25\x33\xa7\x85\x35\x5b\xde\xcc\x5d\xcb\x3a\x0c\xa9\xba\x65\xd1\x99\xa8\x02\xad\xe5\x69\xcc\xba\x71\x7a\xe2\x14\x50\x3d\x3b\x67\x59\xa7\xe5\xef\xb4\x3a\x45\x77\xc1\xf2\x1c\x00\x81\x66\x08\xf9\xe7\x41\xd6\x9d\xc2\x4c\x16\xec\x30\x66\x0b\x40\x83\x93\x7a\x57\x49\xb8\x60\x7e\x2b\x5c\x2e\x5b\xde\x32\x2c\x4e\xfd\xd6\x7e\xcb\x3b\x85\x09\x8b\x59\xe6\x4f\xd7\xde\xc6\x1a\x6a\x14\xb2\x70\x0c\xc0\x6e\x2c\x9d\x0b\x74\xeb\xe2\xf3\xad\xc5\x8b\xb0\x58\xe5\x0a\x22\x9f\x0f\x4b\x57\x5e\x6e\xab\x3c\x85\x79\xaf\x56\xdd\xf7\xe1\x2d\x00\x1c\x6f\x6f\x23\xf4\xae\x0c\xf8\x80\xd5\x74\xb3\x55\xe2\x9c\x7b\x51\xf7\x51\x94\xc3\xac\x5e\x3e\x81\xf9\xc5\x09\xb0\x67\xa2\x9b\xc1\xac\xb1\xcc\xa9\x36\x57\x78\xc9\x2a\x8e\x81\x8c\xd2\xe9\x0a\x5f\x74\x8f\xd3\xd9\x25\xcc\xc6\xda\xbb\xaa\x11\x9b\x7f\x70\xeb\xb6\x67\xac\x17\x78\xfe\xd1\x6b\x5e\x0c\xf0\xe9\x27\x6f\x03\xad\xfb\x07\xb7\x7b\xd5\x6f\xc6\x3a\x81\xcf\x07\xde\x96\x95\x00\xdf\xa9\x57\x5c\xc0\xfe\xc1\x9d\x5b\x9e\x5e\xac\xf0\x78\xc7\x93\x6b\xd5\x3f\xf8\xfe\xb6\x47\x4c\xc1\x3f\xe8\x01\x30\x16\x7f\xf0\x6f\xf7\xd6\x13\xef\xa0\xce\x68\x76\x8d\x17\x20\x2e\x1a\x98\xda\x8c\x01\xc7\x06\x9e\xc6\xff\x76\xc3\xc5\x6c\xc4\x7f\x3a\xe3\x49\xc3\x7a\x29\xba\xf7\x56\x45\x1a\x47\xc9\x19\xcb\x82\xcc\x01\xd4\xfa\xad\xf4\xf8\x03\xd2\xa5\x6a\x32\x19\x31\xc9\x50\xb1\x88\x5f\xab\xe3\x14\xa7\x51\x6e\x36\x8e\x6b\xa5\x08\xd4\x0b\xe6\x5e\x15\xdd\x37\x30\xea\x6e\x98\xe7\xd1\x49\xc2\xcb\x33\xbe\xa6\x92\x00\x9f\xba\xa7\x61\x7e\x5a\x84\x27\x28\x9b\x92\xdd\x20\xd8\xed\xb7\xdb\xad\xe2\x22\x2a\x10\x1d\xf0\x9c\xc0\xe3\x3c\x9c\xb2\xe3\x34\x3d\xa3\x67\x97\x8b\x20\x43\x60\x45\xc9\x79\x18\x47\xb3\x9d\xff\x16\x4d\xfd\xf7\xce\x74\x7e\xb2\xb3\xb7\x93\x33\xb6\x03\xf4\x93\xb7\xdc\xf5\x40\x8d\x7a\x99\xa5\x45\x8a\xe3\x0b\xae\x70\xfd\x17\xd9\x6a\x0a\xd4\xe9\x17\xde\x2a\x8b\x73\x7f\xb7\xe7\xb1\x45\x18\xc5\xf8\x43\x00\x81\x3f\x97\xa7\x30\xe3\xf8\x43\xf4\xe0\xef\xf6\x3d\x00\xe0\x0f\x10\x91\xe9\x05\xbe\x47\x11\xb0\x7c\x91\x01\xbe\x3f\x51\x55\xa0\x7d\xa0\x76\xe6\x9f\xa7\x00\x57\xcf\x3b\x63\x6c\xf9\x3c\x8b\x4e\xa2\x24\x8c\x5f\xb3\x4f\x05\xd6\x9f\xc6\x80\x93\x67\xb4\xec\x60\x65\x15\x8b\xf8\x45\x98\xc1\x8a\x93\x55\x16\x61\x31\x3d\xb5\x5f\x41\xc7\x3f\xaf\xa2\x78\xa6\xdf\xe0\x54\xf8\xe6\x7a\x92\x62\x8f\x71\xdc\x9e\xb0\xe2\x91\x6a\xd9\x71\x3d\x10\xae\xdd\x25\x3e\x40\x59\x2f\x0b\x7a\x20\xa1\x80\x38\x52\xf8\x11\x06\x89\x92\x7e\xc3\x74\x90\x82\x04\xbc\xe2\x52\x27\x19\xa7\x13\x10\x36\xd4\xd8\x6b\xc0\x9b\x83\xc2\x86\x3f\xc1\x48\x1c\x52\x2a\x5a\x8c\x2f\x5b\x20\x9d\x60\xe5\xb6\x42\xfc\xcb\x8b\x84\x27\x38\x44\xc7\x6d\xb7\x9d\xbc\x1b\xe5\xf7\xe3\x34\x87\x15\xe3\xb8\xa3\x2c\x78\x0a\x6c\xa6\xbb\x08\x3f\x39\xd9\x5e\xdf\xeb\xb9\x7e\x06\x7d\x02\xbb\x58\xae\xf2\x53\x67\xea\x0e\x58\x0c\xa2\x95\xda\x4e\x8a\xa8\xb8\xa4\xa6\xcb\xb2\x85\x8b\x5c\xf5\x54\x2f\xdd\x83\xf7\x19\x07\x3d\xe6\x38\x40\x1c\x45\xf3\xcb\x57\x45\x86\xe5\x44\x8d\xd8\x5d\xf3\x1a\xb2\x01\xa9\x44\x44\xdd\x0f\x69\x04\x52\xa3\x85\xca\x86\xaa\xe9\x37\x48\x0f\x89\xe0\xa7\x7a\xa2\x1c\x17\xd8\xd9\x32\x06\x6a\x85\x55\x4a\xdf\x39\x53\xa3\x22\x2f\xa9\xda\xdb\x30\xa6\x2f\xd0\x7c\xd3\x37\xdf\x5c\x3a\xb4\x48\x10\xbd\xd4\x94\x68\xf9\x21\x2c\x08\x47\x2c\x1d\xf5\x8a\x2b\x55\xb4\xb8\xc4\x0a\x73\xbd\x16\xd2\x64\x72\x62\xac\x66\xa9\xf9\x51\x9b\x49\x80\x6b\x4d\xbe\x62\x6a\x24\x6c\xa6\xa7\x15\xd0\x01\x2b\x24\x4c\xa6\x58\xbd\xe8\x22\x29\xc1\x84\xaa\x66\xba\x45\x7a\x2f\x99\x9e\xa6\xd9\x2b\xea\xc9\x71\xa5\x06\x24\x30\xf3\x5a\xd1\xab\x83\xba\x50\xd6\x3d\xc6\x27\x18\x99\x52\xaa\x6a\x2d\xac\x3d\x8b\x64\xfd\x0a\x6b\x11\x64\xad\x57\x8b\x6c\x89\x81\x66\x51\xfb\x48\x4a\x6d\x61\xbc\xe8\xea\x96\x5d\x8f\x51\x5f\xc6\xec\x6d\xe8\xcc\x58\x88\x0d\xbd\x19\x5f\x45\x77\xc6\x9b\xae\x49\x1b\x57\xc4\x60\xa8\x12\xfe\x12\x7c\x86\x9e\xe9\xa7\xe2\x37\xf4\x4a\x3c\x08\xce\x43\xaf\xe8\xa7\xe2\x40\x26\xef\xb4\xd8\x0f\x7d\x30\x5e\xd4\x99\x0f\x95\xa8\xbe\x05\x99\x2d\x50\xa2\xa7\x6d\x03\x46\x34\x1f\x6a\x40\x88\xfe\x28\xf0\xc1\x27\xd8\xa0\x85\x2b\xcd\x39\xa9\x86\x7a\xd4\x6c\x93\xb7\x24\x9e\x0c\x4e\xc9\xd7\x94\x7c\xe4\x20\xaf\xbd\x82\xd6\xb8\x21\x75\x50\x60\x72\x52\x24\x10\x9c\x44\x51\x5c\x46\x45\x81\x04\xb1\x16\xcd\x54\x70\x85\x3f\x0d\xa2\xb9\x52\x9f\xcc\x17\x28\xc4\x82\xab\xf0\x18\x10\x0b\xe2\xfa\x29\x2b\x4e\xd3\x99\x89\x1e\x12\x4a\x2d\xf9\xbd\x05\x55\xb2\x68\xf1\x92\x9d\xb0\x4f\xfe\xfe\xbf\xc7\xef\xf3\xf7\xab\x87\x87\x0f\x1f\xbe\xff\x74\xaf\x37\xe9\x94\x95\xe7\x6f\xf6\x4f\x3c\x2e\x1f\x7d\x53\xec\x6b\x6e\x8e\xeb\x70\x87\xb9\x0c\xe7\xfb\xf9\x45\xf2\x22\x4b\x97\x2c\x2b\x2e\x61\x5c\xc0\x0b\x8a\x71\x32\x01\x9b\x29\xd1\xb6\x4a\xb1\xf6\x60\x42\x41\xaf\xf2\x9b\x50\xc2\xb4\x08\x84\x45\x69\x0c\x61\x8d\xcc\x51\x49\xc7\x8c\x16\x33\x48\x02\x10\x0c\x95\x6e\x5b\x86\xe0\x6c\xb9\x23\xe0\x3e\x86\x20\x35\x35\x0d\xf3\x43\x17\xf4\xe4\xf8\x92\xf3\xa8\x30\x3b\x21\xa5\x0e\xb8\x20\xf5\x12\x06\xa9\xd1\x33\xce\x59\x24\xc7\x12\x9a\x6d\x04\xa9\x17\x76\xf3\x15\x40\x41\x34\x10\x64\xde\x0c\x04\x4f\xc1\x76\x2c\x10\x3c\x5b\xe5\x08\x61\xe8\x5e\x0a\x28\x89\xe3\x68\x99\x47\xb9\x5f\x55\xad\x94\x6a\xc0\xe5\xdf\x90\x11\x83\x45\xf5\x13\xb4\x8d\x51\xab\xdb\x6d\xf9\x89\x57\x04\x60\x21\xac\x8e\x39\x4f\x75\x40\x4b\xd8\x93\xf2\xd2\xed\x40\xfb\x80\x72\x20\x61\xf6\xe9\xf9\xbc\x32\x85\xc0\x45\xef\x65\x59\x78\xa9\xc7\xd7\x15\x05\x5d\xd5\xaf\x78\x81\x8c\x51\xcd\x38\x88\x64\x60\xa4\x52\x24\x67\xc3\x64\x90\xa0\x51\x3a\xe7\xd3\x1d\x04\x4c\x33\x73\xfe\x63\xaf\xbf\xf6\xf2\x65\x1c\x15\xf7\x92\xd9\xfd\x70\x09\xaf\x58\x1d\x94\x5d\xe0\xf3\x71\x7a\x1c\xc6\x75\x25\xea\xbf\xa9\x32\x51\xec\x7f\xef\x2c\x56\x79\xb1\x73\x1a\x9e\x33\x90\x72\x60\xfd\x9f\x7c\xbb\x33\x8f\xc3\x13\x50\xa8\xc0\xf0\xd4\x30\x02\x84\xa0\x3d\x44\x60\x3b\xa3\x5e\xc1\x3e\xb1\x29\x88\xc7\x81\x9b\x71\x99\x6a\xe2\x2b\xf2\x12\x3e\x4a\x17\x0d\x07\xfa\x9c\x8c\x7b\x13\x94\x0a\xe2\x43\x07\x9f\xd5\x70\xe5\x62\xad\x37\x84\x0d\xf0\xc5\xd5\x28\x93\xb5\xfc\xe5\x1c\x44\xac\x41\x0f\xe5\x39\x2e\x63\x21\xc2\x02\x41\x22\x7c\x99\x38\xcf\x49\xef\xf5\xae\x2e\x4e\xa3\x82\xe5\x4b\xa8\x2f\x56\xee\xfb\xbc\xb3\xef\x35\x52\xf7\x26\xcd\x96\x8b\xfd\x08\xcc\x86\x0c\xfb\x0a\xec\xc7\xb2\x34\x9e\x5f\x3f\x7d\x02\x53\xa6\x74\xa4\x8d\x3a\x46\xc1\xbf\x07\x5c\xa5\x90\x2c\xda\xae\xd2\x58\x03\xb4\xa5\x16\xf5\x70\xaf\xb0\x54\x18\x4f\xea\x16\x4a\x52\x63\x81\xdc\x51\x0c\x24\x19\x17\xc0\x52\x74\x77\x95\xfa\x35\x15\x48\x54\x87\x5a\xaa\xbb\xbc\xae\xc9\x6c\xea\xcd\xc6\x63\x22\x91\xa8\x7a\xce\x37\x0d\x33\xc4\x8f\x20\x79\xf4\x03\xf0\x6a\x97\x40\xb8\x8f\xfc\x61\x23\xc8\x02\x46\x60\x64\x58\xac\xe5\xa1\x67\x29\x9c\xcd\x2a\x95\x4c\x06\xec\x69\xad\x86\x4a\x91\x42\x43\x6f\x2a\x34\x03\xca\xb4\x18\x8f\x58\xd5\xa0\x59\x67\xa3\xac\x4b\xab\x0b\xc8\xd7\x87\x15\x93\xc3\x6a\x91\xcf\xb0\x74\x00\x9e\xd3\x68\x8e\x2a\x97\xbb\xd7\x87\xa5\x9d\x12\xcb\x6a\xb7\x43\xb1\x50\x34\xa2\x2a\xe8\x16\xe0\x4f\x82\x50\x28\xad\x3b\x2d\x89\xba\x8c\x2d\xd2\x73\xf6\x7f\x32\xa0\x50\xac\x62\xe2\xa2\x6a\x6c\x30\x38\xe1\xbf\xe4\xc3\x1b\xec\xf5\xc1\x98\x5b\xe1\x28\xb1\x26\xac\xd8\x95\xd7\x57\x5a\xf8\x17\x8c\xf4\xa4\x36\xd9\x1b\xc9\x53\xb6\xc2\xd7\x05\x08\xb5\x4d\x54\x42\xb0\x61\x27\x9d\x0a\x8e\x3a\xd8\xb1\xe2\xd7\x54\x80\x5e\x11\xcd\x3d\x96\xab\x7c\x23\xdd\x19\x6c\x41\x43\xdf\x50\x6d\x43\x2d\x0e\xb7\xad\x32\x57\x55\xb4\xc2\xd4\xbe\xb9\xe9\xe5\x09\xcd\x8c\xb4\x6f\xc2\x05\xda\x42\x8a\xaa\x58\xc0\x46\x38\x12\xb2\x43\xc7\xad\xbb\x2d\x72\xac\xb6\x86\x2d\x4f\xb6\xa4\x20\x84\xb6\x5a\x77\xf7\xb1\x00\x7c\x9e\x18\x96\x92\xd5\xb4\x09\x12\xca\x1c\xbd\x3c\x85\xcc\x6a\x71\x57\x69\x51\x65\x08\x00\xe8\x78\x32\xb0\x94\x9e\xc2\x2d\x9a\x94\x1e\x26\x96\x46\xe7\xdb\xa0\xf5\x6d\x07\x45\x62\xe7\xdb\xd6\xb7\x7a\x48\x9a\x4a\xd6\x6b\x20\x94\x9a\x0e\xba\x81\xff\x7f\x11\xa7\x17\xa3\x6e\xe0\x73\x5c\xef\x15\xa2\xc6\xb9\x12\xdc\xd8\x07\xb3\xd8\x23\x34\xf8\x86\x69\xc8\x87\xce\x0c\xe3\x9a\x7e\x73\x80\x1f\x81\x02\x8f\xce\x4f\x45\x01\xc2\x10\xc8\xd2\x29\xcb\x73\x31\x28\xb4\xd6\x8c\x3a\xdc\x7a\x43\xbf\xa5\x64\xe6\xd2\xd2\xac\xf0\x52\x43\x0c\x5c\x9d\x42\x47\x3e\x68\xff\x82\x29\xf0\xf2\xf7\x73\xbe\x40\x50\xa8\x4b\x89\x8c\x8b\x5a\xaf\xc6\x4c\x88\x3b\xa5\xc1\xe3\x67\x90\x3e\x19\x40\x13\xb4\x8e\x8e\xe3\x30\x39\x83\x85\xaa\x20\x90\x2d\x5a\x0b\xc4\x30\x2c\x94\x66\xaf\x26\x72\xc4\x3a\x44\x9b\x9d\xd6\x1e\xac\x35\x1f\xe9\xbf\x36\xfa\xc6\xe5\xc6\x1b\x9c\xa5\xaf\x85\x11\xe1\x20\x8f\xd7\x8f\xd6\xac\xd9\x72\x48\xea\x89\x0e\x17\x80\xca\x0c\x29\xcb\x67\xab\xc5\x31\x18\x75\x2f\x9e\xbf\x7a\xfc\xfa\xf1\xdb\xc3\xa3\xc7\xcf\x1e\x3e\x7e\xf6\xf8\xf5\x3b\x41\x64\x8d\x76\xe6\x06\x4a\xc3\xb2\x5c\xc7\xa8\xad\xdf\xfd\xdd\xbd\x3d\x07\x2d\x84\x57\x93\xce\xc8\xdd\xdb\xdb\x87\x65\xb1\x3f\xee\xed\xfd\x14\xee\x7d\xbe\xb7\xf7\xd7\x44\xff\xf4\x27\xdf\xed\x7b\x09\x7c\xfc\x37\x94\xee\xb5\xbe\x1d\xbe\xdf\x0f\xde\x7f\xea\xf5\xf7\xde\x7f\xea\x83\x69\xf1\xc3\xc3\x09\x68\x2f\x59\xb0\xef\x8c\xfc\xd6\xf8\xdf\xad\xc9\x77\xa3\x56\xf9\xed\xf8\xdf\xdf\xc2\x8f\x6f\x4b\xf8\xdb\x0a\xee\x0e\xff\xfb\x7d\x3e\xe9\xb8\xfb\xa4\x88\xe5\xe9\x2a\x9b\x02\xaa\xa1\xfc\xfb\xf7\xf9\x77\x01\xfe\xd7\xea\x64\xea\xbd\x3b\x6a\x29\xa2\x02\x12\x07\xf8\x0f\x3f\x2d\x9d\x31\x96\x6f\x01\x63\x70\x76\x1f\x3c\xbf\xff\xfa\xdd\x8b\x43\x17\x9e\xf8\x3b\x68\xa1\x23\x1f\x22\xaf\x55\xb6\x3c\xa3\x35\xf8\xe0\x7e\xd7\x22\x4e\x43\x0f\xa5\xaa\x76\xd7\xd9\x87\xbe\xc4\x53\x21\x6a\x98\x05\x1c\x20\x09\xab\x21\xb3\xbb\x48\xb4\x8b\xe0\xef\x8f\x44\xe3\xae\xea\x48\xf3\x2d\xaf\x75\x12\x01\x87\x80\x35\x87\xd3\x71\xff\x34\x44\xd3\x8d\x65\x87\xe8\x6f\x8a\x58\x2e\x74\x40\xa7\x9d\x1c\xe7\xcb\x41\xd9\xfe\xcf\xfe\xf7\x3d\xf8\x13\x17\xf8\x9b\x7e\x9e\xf0\x9f\x07\xf0\xff\xc7\x55\x4a\x0f\xb7\x6e\xd3\xff\x3f\x0d\xdc\xfd\x93\xc8\x23\x5f\x5b\xb3\x83\xce\x53\x22\x58\xd1\x02\xaa\xd2\x20\x6e\x81\x07\xa2\xf1\x81\x22\x08\xcc\x30\xa9\x57\x4b\x01\x1a\x82\xad\xd7\x23\x91\x3b\xbe\x85\x7e\x39\x36\xee\x83\x40\x63\xe3\xdb\x13\x6f\x1a\xec\xee\xb2\xf1\xc1\x04\x37\x7c\x2c\xe5\x5b\xd8\x1c\xee\x20\xd6\xbe\x23\x02\x0d\x97\x0f\xd8\x0b\x34\xe2\xcb\x67\xe9\x8c\xe5\x4e\x0c\xc6\x12\x71\x57\x61\xb0\xa5\x20\xac\xe5\x2b\x27\x1f\x99\xfc\x81\x7b\xe2\xb0\x1a\xed\x59\x9a\x6c\x4d\xb8\xf1\xc5\xb7\x95\x37\x45\x2e\x16\x08\x38\x3a\x52\x45\x58\x83\x78\x88\xee\x4a\x2b\x87\x8f\x6f\x69\xc3\xee\x0e\x96\xd7\xc3\xbc\x6c\x82\x59\xea\x12\x60\xfa\x6d\xa8\xd7\xac\x19\xa1\x4d\xa3\x96\x6d\xc5\xa2\x92\x3c\x61\x33\xbd\xb8\x62\x12\xd5\x5e\x62\x3a\x8c\x06\x51\x27\x38\x90\xb3\x97\x8d\x23\x9c\x3d\xf8\xd3\xe9\x4f\x06\x61\xbb\x9d\x08\x2b\x47\x23\x0f\x21\xe5\x98\xc3\x8d\xaf\xa6\x12\x7a\x10\x4e\xae\x47\xaa\xf9\xac\x9e\x99\x8a\x0b\xc0\x58\xbe\x16\xc3\x32\xe7\xf2\xaa\x40\xa6\xca\x3c\xe1\x69\xf5\x05\x2a\xd0\x98\x02\xe1\xbb\x56\x9e\x4b\x63\x8e\xad\x5e\x70\x7f\x62\x53\x3f\x26\x5d\xc8\x7e\xa4\x7c\x44\x7f\xe2\x93\xf4\x82\x65\xf7\xc3\x9c\xbc\xcc\xdc\x57\xec\x67\x46\x97\x6a\xdc\x4d\x0c\xbc\xde\x9b\x46\x93\xe8\x4c\x37\x25\x91\x7c\xa3\x86\xd4\x8c\xe8\x66\x9a\x58\x3e\x16\xd9\xc0\xf0\xa9\x1e\x28\x58\x5f\xa8\x62\x08\xb5\x40\xce\x81\xed\x7f\xf2\x84\x0f\x7e\xa3\x19\x88\x6e\xbd\x2a\x9c\xc6\x4c\x57\x40\x6d\x1c\x0e\x2a\x45\x9c\x0c\x00\x78\x09\x4d\xad\x3f\xe5\x95\xe7\xfa\xb8\xa8\xb1\x01\x2c\x51\xb6\x06\x99\x41\x1b\x37\x83\x4c\x29\x56\x2d\x45\x2b\xbb\xfd\x2d\x40\xca\x4d\x8a\x2f\x30\xa1\xd7\x9e\xda\xb3\xd8\x38\x1c\xfe\xb9\x3e\x1c\x45\x7c\x37\x1b\xcd\x16\xb8\xf9\x06\x48\xad\x07\x49\x95\x7f\xb7\x7d\xa4\x13\xd1\xfa\x06\xe7\xf5\x06\xa2\xfe\xd2\x2d\xb3\xca\x2e\x19\x75\xc6\xb2\x4d\x7a\x90\xf3\x6f\x50\x52\xde\x5f\x4c\xdc\x7f\x39\xef\x2f\xae\xfa\x5e\xff\xce\xda\x25\x65\x48\x7d\xf8\x4f\xf3\x43\x42\x8a\xce\xf8\xfd\xde\xc0\x6f\x07\xef\x3b\xef\xbf\xf1\xde\x5f\xbc\xef\x4e\x3a\xff\x72\xa5\x12\xf4\xbe\x33\x7a\x3f\x83\xf2\xb7\xd6\xe3\xbd\xf7\x79\x77\xe2\x8e\xde\x3b\xf8\xe6\xd6\xfa\xbd\x3b\xe2\xaf\xf8\x23\xff\x0d\x3f\x6f\xaf\x51\x33\xa2\x76\x41\xdf\x02\xad\x6b\x32\xde\xeb\x76\xf8\x4f\x50\xc3\x26\x1d\xdf\x19\xed\x6e\xfa\xf4\x7e\xff\xfd\xbe\x0b\xdf\xdf\xcf\x3a\xef\xf7\x47\x2e\x02\x80\x6f\x46\x00\x4f\x4a\x6d\x5e\x5c\x00\x80\xf0\x14\x82\x0a\xa7\x2a\xbe\xef\xbe\xdf\x9b\x7c\x67\x3c\xef\x4d\xf6\x41\x5e\xec\xbf\xef\x42\x8d\x28\x01\xec\x26\xb4\x8d\x1e\xc6\xa5\xe2\x25\xf0\x88\x0f\xc4\x1a\xd2\x2c\x2f\x19\x16\x5b\x66\x51\xce\xf2\x12\xe6\xa1\x48\x4f\xb2\x70\x79\x7a\x59\x82\xea\x3c\xe3\xc5\xf3\x72\x9e\xae\x92\x19\xb5\x54\x46\x8b\x45\x7a\x1c\xc5\x11\x83\x9f\xc9\x6c\x85\xb3\x04\x15\x17\x61\x12\x9e\xd0\x82\xc1\x7a\x68\x7b\xe1\xdb\x82\x4d\x4f\x93\x34\x4e\x4f\x2e\xcb\xe9\x29\xf4\x50\x2c\xc2\xbc\xc4\x15\xbd\x4a\x80\x46\xcb\x59\x94\x31\x84\xe1\xb2\x64\xd0\x13\x6f\x1e\x63\x6c\x96\xd4\x0e\xee\x26\x45\xc5\x0a\x74\xe9\x45\x98\x9d\x31\xdc\x3b\x2f\xf3\x34\x5e\x71\x88\xce\x43\x5e\x21\x2f\x8f\xc1\x82\x08\x23\xfc\x91\xc2\xb7\x8f\x2b\x56\x1e\x73\xbb\x0d\xba\x02\xd6\x8d\x9a\x41\x39\x8d\x59\x98\xf0\x1f\x29\xac\x43\xfc\x91\x2e\x96\xb8\x89\x5e\xce\xd8\x22\x9d\x66\x61\x01\xd0\x84\x8b\x34\x99\xe5\x25\x8d\x3f\x9a\xe6\xe5\x69\x1a\xcf\x70\xc7\xbe\x8c\xa3\x93\x53\xea\x1f\x74\x83\x22\xc1\x96\x97\x31\xa8\xf7\x04\xd1\x0a\x94\x08\x1a\x6b\x06\x40\xe0\x9b\x73\x00\x1e\xa4\x7f\x5e\x02\x84\xd0\x38\x0c\x3d\xcc\x18\x41\x03\x5d\x86\x09\x3c\x67\x2b\x42\xf6\x2c\x5d\x10\xdc\xb8\x69\x9e\xb3\x59\x39\xa7\x6e\x00\xd9\x71\x8a\xb8\x2a\x4f\xc2\x38\x66\x80\x9c\x93\x55\x04\x56\x12\x81\x13\xcd\xc2\xcb\xf2\x2c\xc2\x95\x90\x94\x09\x03\xec\x87\x59\x99\x9e\x45\x49\x78\x11\x96\x80\xcc\x68\x09\xed\x66\x00\x40\x18\xe3\xdf\xf3\x88\x5d\xe4\x65\x7e\x1a\x9d\xe5\xa7\x61\x89\x8c\x27\x86\xef\x08\x72\x9a\x15\x65\x7e\x99\x17\x6c\x01\x70\x9e\xb0\x64\x7a\x59\x82\xb5\x12\x47\x40\x1a\xc0\xc8\xb2\xb0\x9c\x12\x59\x00\xcc\xf3\x39\x63\x48\x2f\xb3\x14\x20\x0e\x09\x0b\x0c\xc3\x46\x58\xc9\x70\xa4\x04\x3e\x4c\x77\x39\x5f\x15\xc7\x69\x5c\x9e\x85\xab\x39\xc0\x16\xaf\x3e\xad\x00\x74\x18\x60\x0e\x93\x0a\x78\x85\x75\x5d\x2e\x56\x39\x5b\x2d\x4a\xa0\x94\xf4\x32\xe4\xb4\x86\x50\x2e\xc3\x28\xc3\x3f\x04\x53\x3a\x8d\x80\x58\x09\xab\x97\x25\x74\x53\xa4\x69\x09\xb4\x04\xd4\x87\x18\x3e\x67\x71\x79\x1e\x85\x1f\x60\x14\xe7\x51\x0c\x06\x20\xfc\xc9\x91\x6c\xce\x53\x82\xec\x1c\x1a\x3e\x61\x25\x51\x36\x27\x03\xc4\x3e\xcc\x29\x20\x2c\x5c\x96\x18\x87\x86\xa3\x48\xa6\x00\x3d\xb2\xa1\xf2\x04\x8d\x48\xc0\x2c\x40\x86\x34\x7c\x92\x96\x30\x87\x1f\x42\x9a\x68\xb1\x1c\x00\x7f\x29\x62\x2d\x8d\x01\xd7\x45\x8a\x33\x50\xa4\x67\x97\x00\x56\x9a\x02\x96\x2f\x90\x2f\x95\x17\x69\x76\x06\x98\x64\x59\x5a\x86\xd9\x32\x2c\xc3\x3c\x0a\x01\xa3\x30\x8b\xc7\xd1\x19\x50\x64\x4c\x64\xf9\xf9\x33\xa2\x17\xe0\x88\x57\xc7\x00\x4c\x8a\xab\x32\x5d\x96\xf3\x30\x5b\x94\xf3\x08\x30\x74\x12\xcd\x61\xde\x57\xd9\x0a\xa8\x7f\x9e\x96\x1f\xd2\xe3\x1c\xa6\xfb\x22\x2a\xcf\x32\x20\x10\xb0\x90\xe1\xbf\x68\x91\x96\xb8\x2f\x55\xc2\x2a\x59\x95\xb8\x18\xe1\x3f\x40\x0f\x06\xe5\x94\x4b\xa4\xdb\x25\x7e\x05\x9a\x2a\xca\x8f\x4b\xc0\x4d\x16\x01\x80\xd9\xea\x34\x2b\x73\xf6\x09\x80\x07\x83\x15\xf1\xc5\xf0\xbf\x14\xe0\x07\xbc\x5d\xe0\x72\xbe\x88\xce\xa2\xf2\x33\x30\x62\x5c\x52\x00\xf7\x0c\xfe\x21\xc0\xc7\xb8\x8e\x80\x20\x52\xa4\x60\x5c\xaa\xe5\x49\x7a\x0e\x00\x16\x00\xda\xa2\x5c\x00\x16\x13\x56\x94\x69\x12\x97\x69\x76\x82\xcb\xbf\x5c\xc2\xf0\x10\xe0\x02\xa6\x6b\x95\x40\x1f\xf0\xfb\xd3\xa7\x4f\xe5\xa7\xcb\xcf\x30\x37\x65\x38\x03\x4c\x95\xe1\x1c\x28\xaf\x0c\xa3\x12\xe6\x3b\x5c\x94\x61\x52\x86\x80\xbc\x8f\x80\x3f\xc0\x5e\x09\x3d\x86\xab\x32\xbc\x28\xc3\x4f\x65\xf8\x19\x20\x2a\x8f\x8f\xcb\x63\x00\x09\xa0\x9b\x97\xc7\x27\xe5\xf1\x29\x80\x57\x1e\x7f\x28\x8f\x17\xe5\x71\x02\x8b\xbf\x3c\x06\xa0\x81\x0b\x00\xca\xcf\xcb\xe3\x8b\xf2\x18\x48\x1a\xc1\x2f\xa7\xd3\x72\x0a\x74\x30\x2f\xa7\xb0\xec\x4f\xcb\x69\x54\x4e\xcf\x60\x0a\xca\xe9\xa2\x9c\x22\x2b\x84\x05\x59\x4e\x57\xe5\xf4\xbc\x9c\x5e\x94\xd3\x4f\x25\xac\x85\xe9\x67\xe0\x0b\xe5\xec\x43\x39\x3b\x2b\x67\x0b\x58\xa9\xe5\xec\x73\xc9\xa6\x25\x2c\x05\x06\xf4\x9f\xc1\x12\x28\x61\xcc\x6c\x05\xd3\x56\xce\x3f\x94\xf3\xb3\x72\x0e\x53\x98\x96\xf3\x0c\x96\x6d\x79\x72\x5c\x9e\xcc\x4a\x20\xc4\x93\x79\x79\x72\x52\x9e\xe0\xc4\x02\xa9\x95\x27\x8b\xf2\x24\x29\x4f\x96\xe5\xc9\x47\xe0\x32\x25\x70\x96\x13\x9c\xee\xf2\xe4\xa2\x04\x16\x79\x7a\x56\x9e\x2e\xca\xd3\xa4\x84\x99\x3a\x2d\xca\x53\x20\x82\x59\x19\xb1\x12\x10\x0c\x78\x86\xa5\x19\xa5\x65\xf4\xb1\x84\xc5\x12\xe5\x65\x54\x94\x1f\x58\xf9\x61\x01\x34\x52\x7e\x58\x96\x40\x63\x67\x27\xe5\xd9\x29\x4c\x49\x79\xb6\x28\xcf\x92\xf2\x0c\x5e\x66\xe5\xd9\x45\x79\x06\x1c\xe3\x33\xd0\x4e\x19\x1f\x97\xf1\x14\x48\xa7\x8c\xcf\xca\x38\x2b\x81\x76\xe3\x02\x16\x6a\x19\x9f\x97\x31\x2e\xd5\x72\x31\x2d\x17\x33\x20\xab\x72\x71\x52\x2e\x60\xb9\x02\x89\xc5\xe5\x02\xa6\x18\x57\x70\x09\x74\xbb\xf8\x58\x2e\xb2\x12\x58\xc6\xa2\x80\xc5\x5c\x2e\xce\xcb\xc5\x45\xb9\xf8\x54\x02\x93\x5b\x7c\x06\x02\x2c\x93\x29\xd0\x42\x99\xcc\x4b\xa0\xa9\x24\x2a\x81\x24\x60\xf6\x93\x65\x99\x64\x25\xd0\x6a\xf2\xb9\x04\x02\x82\xd5\xb1\x04\x42\x9d\x97\x4b\x20\x96\xd3\x72\x09\xa4\x1a\x97\x4b\x78\x9f\x00\xed\x94\x40\x9b\x4b\x90\x21\x17\xe5\xf2\xb2\xfc\x88\x3c\xad\x04\x7a\x02\xe6\x07\x4b\x22\xbb\x28\x73\xe0\x62\xc7\x65\x3e\x2d\xf3\x19\x10\x73\x99\x03\xff\x3d\x05\xbe\x56\xe6\x1f\xca\xfc\xac\xcc\x81\x71\x2c\xca\x3c\x81\xb5\x5a\xe6\x40\xed\xc0\x4e\x56\x65\x7e\x5e\xe6\x9f\x80\xd7\x95\xf9\xe7\xb2\x98\x96\x05\x50\xe5\xbc\x2c\x4e\xca\xe2\xb4\x2c\x3e\x94\xc5\x59\x59\xc4\x65\xb1\x28\x8b\x04\xd6\x73\x59\x2c\x81\xcb\x94\x45\x51\x16\xe7\x65\x71\x51\x16\x9f\xcb\x55\x58\xae\x4e\xca\xd5\x59\xb9\xca\xcb\xd5\x65\xb9\xfa\x0c\x92\xa7\x3c\x9f\x02\x97\x2f\xcf\x81\xdf\x44\xe5\x39\x30\x9f\x55\x79\x31\x2f\x81\xd3\x5e\xb2\xf2\xb2\x28\x3f\x87\xe5\xe7\x45\xf9\xf9\xc2\x7d\x7f\xbc\x0f\x36\xf7\x3e\x68\x19\x4a\x40\x77\xda\xff\xfa\xcf\xf7\xfb\xff\x15\xfc\x3f\x47\x8e\x5b\x7e\xfb\xcd\x77\xef\xc7\xef\x27\xa3\x5d\xdf\xeb\x0e\x40\x8c\x5f\x53\x6e\xb2\xdf\xec\x50\x31\xbd\x1e\xca\x35\xd2\xf2\xa4\x8b\x06\x77\x41\xf9\x8f\xbc\xa9\x98\x72\x92\x78\x51\xad\x42\xc5\xd3\xe2\x74\x47\xfb\xe4\x6b\x49\x6f\x5c\x72\x43\xdf\xd2\x0b\xd3\x59\x99\xfe\x22\x0b\xae\xac\x09\x58\x66\xbc\x6c\x72\xcd\x4c\xc1\xcc\xfe\x99\x81\x75\xce\x5e\xe0\x0e\xea\x34\x8d\x5f\xb2\x58\x04\xcd\xf0\xdd\x75\xa7\x0b\x8a\x1c\x68\x56\x5f\xb5\x53\x47\x3a\xe8\x5b\x0c\x1f\x0b\x71\x83\x99\x5b\x7e\x4f\xad\x97\xb8\x9b\x42\x9b\x8a\xb5\x9d\x63\x1d\xee\xa2\xf7\xb2\xac\x0d\x48\x53\xc3\x35\xe2\x1e\xbd\xc8\x4b\xbd\xd0\xcb\xd1\x31\xe2\xc5\xde\xd2\x9b\x7b\xa7\xde\xcc\x3b\xe7\x2d\x2e\x82\x4c\xba\x78\xef\x83\x78\x40\x20\x78\x94\xd0\x96\x8a\x18\xad\xb3\xe0\xd5\x4f\x02\xc6\xc3\x81\x12\x6f\xc1\x01\x50\xee\xdb\x05\xb4\x8b\xca\xf7\xab\x22\xeb\x9c\x74\x16\xdd\x7c\x35\xe7\x4f\x6a\xdf\x05\xed\xe3\xc6\xbe\x2b\x16\x7e\x13\x20\xbc\x7b\x80\x06\xe3\xb4\xa6\xde\x22\x40\x8b\x11\xfe\x43\xd8\xc2\x76\x7b\x57\x85\xbe\x94\x65\x2a\x1f\xb9\xc8\x2e\x63\xf9\x4c\x56\x43\x59\x26\xf2\x59\x18\x14\x65\xb9\x94\x6f\x84\x39\x51\x96\xbb\x0d\xf3\xd7\x8d\x72\xfa\xcd\xd1\x85\xf0\x9d\xbb\x6a\xa3\x7c\x15\xc7\x2a\x98\x8a\xaa\x3d\x0a\xf3\x37\xc9\x71\x18\xa3\xf2\x30\x13\x56\x1e\xd8\x3b\x0c\x69\xa6\xdd\x76\x18\xee\x6a\x91\x27\x0a\xf7\xfb\x85\x3f\x67\xaf\xef\xe2\xa0\x5c\x8c\xe4\x76\x67\x66\xc8\x4f\xf7\x10\xc7\xe2\x5c\x2d\x74\x14\x95\xcf\x84\x69\x94\xae\x75\x84\x5a\xe2\xa2\x17\x1d\x26\xd9\xa3\x0e\x68\xef\xab\xef\x62\xc0\xb4\xd9\xd8\x6b\x3e\xf0\x6a\x73\x02\x1f\x8f\x28\xd2\xd6\x8f\x8c\x66\x63\x8e\xfe\x4b\x68\x53\x92\xe0\xfe\xfb\x07\xfb\x27\xb8\xf5\x3d\xb0\xdb\x7e\x81\x48\xae\xb6\x9c\x90\x73\xdb\xbf\x5c\xcb\xc8\xb8\xb9\xb3\x74\xe7\x04\xe9\x7c\x2b\xa4\x8f\xf8\x84\x54\xdb\xc3\xe0\x61\xa8\xa0\xc3\x76\x64\xac\x92\xb4\x07\x4f\x05\xf0\xb8\x47\x24\x28\xff\x28\x38\xe7\x8d\x0a\x5f\xd7\xf6\xa5\xef\x92\xe7\x13\xe8\xeb\x88\xa0\x3c\xb2\xa1\x5c\xdb\x50\xbe\xc9\x6a\x53\x03\xa4\x08\xff\x2f\x45\xd3\x50\x80\x13\xfa\xee\x6e\xae\x5e\x42\x7f\xa0\x1f\x9f\x33\xf9\xe5\xfc\x9f\x89\xb4\x12\xcb\xed\x4a\xad\x46\x7f\xe1\xa9\xb5\xe8\x9f\x70\xc3\xd8\x9f\xad\xd7\xde\x76\x3a\x6d\xda\x47\x21\xac\xdd\x2b\x9c\x42\x13\x2c\x45\x68\xba\x2d\x8a\x1a\x91\x5b\xf1\x02\xcf\xfb\xef\x9d\xfd\x13\x97\xfc\x9d\xf2\x85\x8b\x2f\x22\x8c\xbb\x95\x11\x2e\x65\x49\x1e\xcd\x76\x3b\xd3\x2f\xe8\x28\xc9\x30\x12\x8b\x6b\xb7\x27\x86\xb4\xdb\xe7\x7e\x04\x9b\x83\x6e\x70\x1f\x88\xb8\xdd\x4d\x7c\x7d\x0c\x26\x3e\xe7\xeb\x40\x32\x0f\x61\xf5\xea\x82\xa2\xc0\x16\xc3\x1b\xc4\x74\x16\xbd\x82\xd9\x5e\xb0\xeb\x8a\x53\xfb\x7f\xa4\xd9\x0c\x3d\xba\xf7\xe6\xb0\xbc\x2a\x1d\xf9\xb8\xc1\x32\xf9\x6e\x24\x1b\xd8\xf7\x4c\x36\xb3\x29\x9e\x88\x49\x8e\x25\x0a\xbf\x91\xf0\x00\x77\x11\x71\x20\x2b\x41\x73\x0f\xc0\x1a\x79\x96\x16\x8f\xc0\x18\x92\x5d\x3f\xcf\x1e\xa4\x05\xed\xd1\x6d\x2e\x7b\xaf\x78\xc2\xc2\xbc\x78\x9e\x30\x09\xbd\x59\x21\xca\x1f\xd7\xf0\xab\x89\x19\xd8\xd0\x68\xb7\xef\xc3\xc4\x79\x55\xf8\x1a\xa9\xca\x58\x96\x36\x62\x5d\x8c\xdb\xb1\x1c\xb7\x42\xda\xb4\x3e\x84\xe7\x61\x3e\x85\xd5\x51\xf8\x18\xb8\x0d\xf8\x68\x9d\x1f\x9b\x2f\xd6\xde\x75\x08\xa8\xec\x56\x0a\x1a\x73\x76\x8b\xb2\x84\xe6\x24\x5b\xa9\xd1\x46\xb7\x00\x33\x8d\xd0\x4c\x3b\xf9\x3a\xc2\xaa\xd5\x6d\x01\x67\x68\xea\xb6\x8e\xcb\xc6\xbe\x77\x8a\x76\x9b\x8d\x94\x24\xda\x4c\x35\x1c\x84\xc2\xf5\x61\x45\x78\xdb\xa7\xa2\x61\xff\x72\x77\xb7\x10\xc3\xdb\xb6\x46\x64\x1f\x86\xeb\x8e\x2f\xbc\x7f\x66\x7b\xfb\x5a\xdf\xb3\x11\x2f\xbc\xc9\x39\x6a\x70\x5c\x1e\xcf\xa3\xf6\xb5\x37\x37\x6b\xec\xec\x36\x96\x31\x46\x4b\x22\xb7\xe6\xfe\x34\x30\xb1\xd5\xad\x8a\x95\xb9\x33\x98\xda\xd9\x34\x06\x2a\x57\x85\xbe\xde\x1c\x96\x2a\x52\x5f\xc4\x8c\x54\x2b\x6d\x43\x12\x2f\x6b\x0c\x4b\x88\xd4\xaf\x1d\x98\x90\xb0\x7c\x68\xa2\xad\x4d\x7d\x8b\xb2\x5b\x86\x67\x84\x6a\x18\x32\x5d\x06\x95\xc8\xd3\x1b\xf9\x45\x44\x0c\xc2\xbd\x9a\x02\x13\x50\x07\x38\x7c\x09\x52\x51\x2c\x73\x7f\x7f\x5f\xbc\xc7\x3d\x80\x7d\x51\x75\xbf\xd5\x61\x03\xaa\xa4\x8e\x79\x54\x6b\x5d\x5c\x5c\x74\xe5\xc7\x5a\xd5\x19\x3f\x42\xe7\xd7\x22\x1a\xdf\x24\x67\x49\x7a\x91\xec\x08\xa8\x77\xd0\x9b\xb2\x53\xa4\x3b\x4b\xb0\x31\x30\xba\x91\x9a\x80\x17\xfe\x0e\x45\x80\x5d\x3b\x59\xad\xff\x14\x73\x2b\x71\x66\xcc\x18\xa9\x54\x5f\x3b\x5f\xa4\xf4\xf2\xd9\xe2\x21\x06\x9b\x26\x8b\xeb\x68\xd7\x93\x62\xc1\x62\x49\x87\xb5\x2a\x37\x5d\xad\xc6\xe0\x84\x2e\xfa\xb5\xc3\x93\xb4\xc0\x39\x8a\xa5\xc0\x6e\xda\x7c\x31\x0b\x5d\x3f\xdc\x26\xe2\x12\xc3\xdf\xd4\xd2\x86\x19\xfe\x57\x63\x35\x03\x15\xa0\x25\x6e\x47\x03\x88\x16\xae\x0c\x2a\xeb\x94\xa0\x93\xbe\x7f\x87\xfb\xfc\x47\xfb\x51\x4d\xc7\x94\x15\xb8\xf6\x22\xbf\x42\x63\x4b\x3c\x21\x37\xdb\xbe\xb5\x05\xdd\x72\xfc\x02\x80\x1b\x16\x2f\x14\xb1\x02\x09\xab\x6a\xa9\x54\x57\x52\xeb\x9d\x53\x7b\x17\x14\xc2\x74\x6e\x54\x92\x85\xf2\x51\xd5\xaa\x2b\xaf\xd5\xa8\x30\x7a\x53\x81\x17\xd0\x4c\xc2\x44\xc2\x2c\x78\xcd\xe5\x03\x3c\x29\x5a\x13\x25\x1b\x63\xe0\x50\xeb\x77\xeb\xb6\xf9\x7e\x3b\x5c\x2c\x07\x68\x1b\xb5\x5b\xee\x16\xaa\xa0\xc6\xb6\x22\x6d\x54\x43\x8f\xef\x54\xba\xdf\x82\x2c\x44\x6f\x60\x5a\x11\x76\x19\x4e\x48\x18\xfb\xe1\x55\x4d\x8d\x4a\xcd\x37\x92\xea\x78\x61\x79\x3a\x08\x63\x40\x5f\x67\x20\x5c\xc0\x60\x78\x15\x87\x18\x43\x80\xea\x8f\x5d\xe5\x06\x71\xd4\x36\x51\x53\x30\xb5\xb7\x05\xe2\x1b\xb4\xd8\x48\xfc\xbc\xe1\x06\xb0\x1b\x1a\x6c\xed\xa3\x3d\xd3\x64\xed\x70\xd4\x08\x43\xb0\xe7\xed\xa1\xc5\xca\xd9\x19\x9d\x1e\x5d\x4f\xbc\x5b\xf5\xe3\x95\xea\xf8\x7d\x46\x67\x39\x00\xc2\x23\xbe\x17\x12\x98\x0f\x65\x89\x67\x41\xe8\xc5\x22\xfc\xf4\x24\xca\x81\x03\xb0\x4c\x96\x31\x5f\x95\x25\x3f\xa1\xb7\x36\xce\xf5\x6b\xd8\xeb\x87\x37\x0b\x5d\x30\x35\x0a\x72\xee\xdd\x58\x2c\x34\x8a\x55\xcf\x6d\xc2\xba\x15\x11\x44\x46\x85\xdc\x98\x0d\x0e\x1c\x22\x70\x6d\x9c\xf0\xf4\xb2\xee\x21\x8e\xf3\x70\xc1\xf9\x3d\xbe\xd0\xc7\x16\x24\x42\xc4\xd1\x43\xeb\x93\x85\x0d\x55\x40\x48\xe6\xa7\xe6\xc7\xbe\x5d\x33\x67\xf6\x67\x73\xa2\x31\x76\x14\x91\x01\xd6\xe6\x10\x14\xfe\x28\x7f\x16\x3e\x43\x02\xe6\x82\x1e\x19\xa1\x10\xf4\x09\x3f\xaf\x70\xcc\x76\x42\x10\xee\x79\x84\x04\xb5\x23\x50\x67\x07\x4f\x57\xa6\x4d\x06\x4b\x1b\x00\x31\x18\xbb\x05\x85\x0a\xd6\xf2\x52\x74\x76\x29\x0f\x92\x22\x09\xeb\x11\x03\xd0\x3d\x71\xe4\x1c\xd1\x0b\xc4\xb8\x6b\x7e\xef\xd2\xa7\xb2\x0c\x9d\xfa\x5b\x57\x72\x60\xeb\xad\x0c\x8e\x22\x7c\xb0\x40\x1d\x9d\x19\xf7\x27\x1e\x33\xcf\xe7\x11\x32\x04\x72\xd8\xa0\x8a\xa4\x6f\xdf\x24\xd3\x70\x75\x72\x5a\x78\x3b\xab\x24\x5f\xb2\x69\x34\x8f\xd8\x6c\x47\x80\xba\x43\x3d\x76\xbf\x75\xd7\x74\x32\xd0\x84\x62\x5c\x4c\xbc\x1c\xac\x45\x69\xe9\xf7\x11\x03\x11\xbe\x10\x2a\x9f\x82\x48\x85\x71\xa1\x32\xb7\xd3\xf7\x8d\x53\x89\xee\xe0\x38\x63\xe1\x19\xa9\x79\x3b\x07\xe6\x17\xcf\x1c\x90\x55\xec\xd6\xc6\x62\xc6\xc3\x81\xaa\x23\xd5\x40\x8c\xe3\xca\x82\x2a\x50\x5e\x4a\xde\x20\x3a\x8a\x83\xe7\x4d\x31\x7d\x42\x7f\x90\x0d\x57\x83\x55\xa7\xe3\xa6\xe3\xd5\x5e\x7f\x62\xe0\x76\x35\x19\x24\xe6\x81\xa5\x54\x3b\xc5\x42\x1c\xfa\xd5\x3f\xd5\x0b\xb6\x33\xc5\xd0\x4b\xe2\x56\xe8\x88\x99\xca\xb6\x56\x41\x4f\x55\x9d\x42\xd9\x0a\x3c\xca\xf1\x62\x91\x6f\x38\x9b\x49\xfa\x0e\x4c\x1e\x67\x1c\x26\xdd\x8d\xc0\xe6\xab\x2f\xa2\x58\x54\x33\xd6\x92\x62\x53\xee\x4d\xa8\xde\x22\x5d\x40\x83\x84\x43\x18\xb2\xb8\xb0\x60\xa9\xea\xf7\x18\x46\x0e\xa0\x74\x65\xc7\xee\x48\xff\xf6\x99\xdd\x1e\x10\xe1\xc8\x5e\x32\xf0\xc6\x1d\x55\x5e\xf0\x30\x39\x26\x02\x11\xf5\xfb\x60\x5c\x25\x68\x36\xa9\x95\x61\x5e\xbd\x83\xca\x82\xc4\x2e\x2e\xc2\x2c\x61\x33\x89\xce\x24\xc8\x9d\x3a\x63\x71\x47\x8d\xbc\xcf\xaf\x97\xf4\xd0\xcb\x36\xec\x09\x14\x19\xdd\x88\xa3\x68\x89\x54\xc0\x6a\x10\x80\x22\xe4\xc9\xfc\x15\x8c\xcf\xa0\x93\xa4\x33\xe6\xee\xe0\x77\x0c\x57\x42\x56\x98\x47\xc7\x31\xdb\x31\x99\xfa\xce\x02\xc4\x6b\x76\xb9\x13\xc3\x9a\xd9\x99\xb1\x02\xe4\x06\x9b\x75\x77\xfe\x6b\xb6\x23\x71\x9f\xef\x00\x11\xe1\xbb\x37\x40\xf0\x8c\xd7\xaa\xf2\x69\xc7\x45\x43\x2a\x4a\x30\x94\x0e\x4a\xc5\x11\x14\xeb\xb6\xaa\x53\x26\x19\x82\xd7\x20\xf0\x24\xec\x68\xd7\xb3\x76\xdb\x7a\x74\x5c\xeb\x20\x88\x4d\xe1\x69\x12\x6c\x20\xf8\x4a\xb1\x29\xab\xac\x00\x25\x09\x13\x29\xe3\xb9\xaa\x21\xeb\x63\xce\x09\x58\x81\x40\xdb\x19\x62\x97\x35\x9f\x58\x24\x16\xf9\x55\x6b\x88\xef\x16\x01\x03\x55\xe7\xa7\x65\x79\x71\xd6\xaa\x4b\x90\x26\x6e\x83\x58\xb2\x21\x6d\x5a\xda\x24\xa0\xf2\xbf\xb3\xc0\x77\xed\x15\x5e\x25\x7d\xd7\x98\x92\x41\xa3\x98\x48\x55\x0e\x01\xe0\x63\x7b\x7d\x0f\x8f\x98\x33\x10\xdc\x8e\x1e\xa9\x4b\x5e\x65\x39\x0c\x74\x48\x8b\x13\x9c\xd5\xb6\x2c\x6e\x62\x8f\xde\x62\x28\xf6\x27\x3a\xbb\xa2\xf7\x44\x34\xaf\xce\x83\x74\x90\xef\xed\x0d\x7b\x03\x3c\x43\x99\x8c\xf3\x09\x87\x0d\x7f\x29\x78\x00\x36\xf3\x91\xfb\xcb\xb3\x20\xe7\x12\x06\xe7\xbd\x37\xcc\x2c\x34\xe0\x71\x2d\x39\xe6\x91\x23\x7f\x05\x3d\xaf\x79\x54\x2e\x88\x34\x71\xda\x29\xf3\xfa\xee\xdf\x1a\xe4\xe6\x15\xc2\x4b\xdf\x8b\xe3\x66\xb5\x4a\x28\x34\xb5\x19\xaf\xce\xef\xee\x16\xe8\x64\x59\x54\x21\xab\x42\xd0\xe2\xca\x20\x19\xaa\x9c\x16\x33\x94\x6c\x9c\xf2\x81\x48\xe1\x50\x57\x2a\x70\x16\x19\x1d\x09\x32\x61\xae\xa2\x86\xfb\x99\x8d\xc5\x6d\xa2\xc1\xc8\x3c\xb0\xa9\x44\xb5\x3d\x7b\x8e\x02\xa1\xfe\x37\x6b\x49\xa4\x14\x6d\xe2\x2b\x9c\x26\x71\x10\x03\x95\x68\x63\x53\xe1\x71\xa2\xac\x19\x7d\xa8\x7b\x0b\xd2\xec\xe9\x8f\x37\xcf\xba\x3e\xf2\x65\x36\x53\x93\x3e\xa3\xa8\x2e\x6a\xab\x22\xb4\x26\x40\xa5\x0a\xe3\x8f\x27\x08\x8f\x84\xe2\x7e\xba\x4a\x8a\x46\x55\x44\x72\x41\xb0\xd5\x34\x20\xaa\x41\x46\x50\x18\x8f\xee\xa8\xef\x9b\xcf\x02\x45\x7e\x6f\xcd\x8d\xba\xdb\xd7\x18\x75\x71\x80\x01\xa8\x92\x46\x31\x83\x09\xc8\x9c\x69\x58\x38\x53\xd7\x5f\x22\xb7\x9a\xaa\x73\x8b\x91\xe3\x9a\x76\x1b\xb7\x44\x62\xe9\x5b\xc0\x13\xbb\xd1\x82\xa5\xab\xc2\xc9\xdc\x01\x34\xdb\x1b\xe8\xac\x2b\xb2\x91\x01\x1b\x48\xc6\x33\xf5\xa6\x78\xa4\xa3\xd3\x59\xde\x85\x97\xf9\x78\x39\xa1\xcc\x48\xee\x80\x7a\xd5\x55\xd6\x39\x9d\x39\xf7\x08\x50\x8c\x6e\xcc\x64\x37\xe8\x9c\x34\xcd\x43\xc4\x21\x61\x1f\x5e\x0a\x23\xa6\x1b\xa2\xce\x19\x30\xd3\x3e\x74\xaf\x28\x17\x5b\x8e\x87\x44\x94\x91\x07\x14\x8c\xe0\xf0\x5e\x10\x82\xc1\x0a\x94\xb5\x4f\x30\xa4\xe9\x59\x9d\x60\x0c\x75\xb6\xba\x22\xc5\xbe\x62\xf5\xf5\xb0\xef\xea\x93\x14\xfd\x41\x72\xb7\x5a\x80\xce\xb1\xb3\x71\x62\xab\xc2\xc9\x64\x30\x15\x67\xfa\xa0\x47\x3e\x46\xd7\xc3\xcd\x9b\xa9\xda\x73\x8c\xcb\xd2\xc0\x7d\xe4\xf5\xc0\x9c\x4f\x4d\xbe\x07\xd8\xb0\x32\x32\x70\x0c\x09\x31\x4e\xb8\xd5\xa8\xc2\x5d\xa0\x6e\x11\x15\x31\x0b\x5a\xc7\x20\x29\x73\xe4\xab\xab\xae\xf8\x89\xf2\x7f\xd5\x65\xc9\x39\xe2\x6b\x05\x35\x4e\xce\x11\x69\xab\xee\x39\xac\x2b\x68\x1e\x43\x1b\xd4\x43\xce\x0b\xc1\xdb\x10\xcb\x1a\x1a\x78\x48\xaf\x41\x11\xa1\x1f\xf3\x39\xfd\xad\x88\x72\xfd\xca\xe2\xd8\xf8\x9a\x6c\x51\xfc\x71\x1c\x25\x18\xb5\x6a\xcd\x4f\xcd\xdd\x2d\xc2\x36\x64\xe1\x9d\x28\xdf\xc1\x34\x7e\x22\x34\x94\xcd\x5a\x34\xe4\xe9\xc5\xcc\x44\x92\x72\xa6\xd0\xb7\xd3\x59\x94\xdd\xac\x13\x2a\xba\xa1\x8b\xd5\x22\xcc\xcf\xea\x9d\xec\xc8\x95\x7a\xe7\xfa\xec\x56\xb5\x44\x54\xed\x76\x6b\x95\xf0\x74\x56\x33\x60\xf2\xe2\x35\xab\xe4\xa7\xfa\xa2\xac\x58\x19\xe6\xb3\x7a\xbc\x58\xac\x8a\x10\x94\xe4\xe6\x74\x56\x56\x7a\x3f\xb5\xb4\xf8\xbe\xec\x15\xe6\x89\x30\xf3\x49\xf1\x6d\x36\x71\x42\xc7\x31\xd2\x6c\xa0\x03\xca\xa0\x53\x33\xa1\x85\xe1\x9f\x61\x96\xb7\xec\x3c\x8c\x57\x0c\xd7\xa8\x51\x82\x4f\x09\xf5\x2a\x3e\xf7\x0c\x46\x85\x4c\xce\x72\x37\x11\x8c\xa8\xe4\xf4\x8c\xb4\x12\x2a\xe9\x52\xcf\x53\x3e\x33\x86\x76\xa7\x5e\xe9\x89\xcb\x73\x3a\xd0\xc1\xa5\x8e\x8b\x07\x96\x82\x62\x1c\x75\x98\xca\xc7\x98\x35\x7a\xab\x0c\xaf\x52\x37\x8f\x3e\x73\xf4\xe0\x0f\xe4\xf0\x47\x11\x98\x11\x88\x97\x9c\xb0\x81\xaf\x2d\x5f\x96\xb1\xc5\xca\x86\x41\x6f\xd4\x61\x3e\x36\xdd\xd9\xe9\x30\xd3\x85\xa5\x36\x48\x0d\xcf\xda\xca\xde\x78\x27\xfd\xa1\x90\x0e\x38\x9e\x41\x6c\x2f\x19\x06\x05\x7a\x06\x15\x88\xcc\x2e\x00\x7d\x26\x06\x2e\xa7\x16\x40\x4b\xea\xc0\xc4\x75\xdc\xf0\x9d\x19\xdf\x97\x95\x58\x00\x8d\x99\x51\xe2\xf7\x86\xc5\xc8\x98\x06\xd6\x29\x5c\x5f\xc3\x35\x2a\x7c\xfe\x31\xc2\x50\xab\xc2\x68\x74\x6e\xa0\x7a\x01\xbf\xa1\xe4\x6b\xc7\x2c\x70\x6a\x14\x38\xe1\x05\x1e\x5b\x05\x66\x46\x81\x4b\x5e\xe0\x85\x55\xe0\xbc\xd2\x05\x18\xc0\x47\xbc\xdc\x03\xab\xdc\xc2\xd8\xaa\xa6\xdd\xf8\xdd\x62\x7c\x9e\x4c\x8c\x12\x27\x0d\x25\x16\x56\x89\xcb\x86\x12\x27\x56\x89\xa3\xca\x78\xca\xf2\xd2\x82\xe2\xb8\xa1\x85\x4b\xab\x85\x43\xce\xc4\x70\x1f\x8c\x76\x2e\xf4\x97\x4f\x8e\x4c\x1f\x4a\x92\x0e\x08\x9e\x66\x87\xf9\x7d\x31\x4b\x63\xf8\xaa\x09\x1e\x2c\x7a\xbe\xe4\x22\x3f\x0b\xae\xe8\xa7\x1f\x79\x33\x3a\xe2\xd2\x07\x7d\x47\x37\x7c\xa1\x68\x54\x14\x13\xee\x50\x5e\xb6\x67\x48\xf2\xfb\xe6\x7e\xff\x53\x6b\x64\x2f\x4d\x5e\x80\x09\xf0\xea\x0e\x63\x1a\x91\xae\xf1\x4a\xcb\xec\xa7\xc6\x81\x6d\x86\x67\xe5\xb9\x17\xcd\x68\xfe\xa9\x11\xd9\x01\x8b\xe2\x13\x2c\x80\x62\xfc\x29\x99\x94\x65\x31\xbe\xd0\x89\x84\x1a\xba\x05\x8e\xeb\x57\x3d\xdb\xcf\x2b\xc0\xd6\x9c\xd6\x52\xc1\x51\x35\x5e\x1b\x35\x78\x9e\x1d\xbd\x60\x09\xfd\x6f\x80\x99\x73\x12\xef\x16\xe9\x2b\xf6\x11\x1e\x1f\x59\x23\x78\x7c\x83\x16\xa0\xea\x6f\xec\x92\xcd\x78\x7d\x6a\xee\xc4\x6e\xb3\xe8\xce\xb3\x74\x71\x98\x14\xd9\x25\x7f\xf1\xd0\xea\xe4\xc5\x8d\xc1\x14\xed\x32\xdd\x12\x76\xf2\x18\xa3\x4e\x64\xff\x3f\x5b\x4d\x3f\xd0\x4d\x3b\x5f\xdc\x34\xb5\xe5\xd2\x28\x0a\x7a\xa5\xdb\x3d\x53\x04\x7f\xc4\x35\x42\xa1\x1e\x0a\x36\x5c\x9d\x88\x67\x9a\x10\x84\xf4\x3a\x63\x97\x74\xe0\x9f\xb7\xc1\xe5\xb0\x6c\xe4\x08\x3f\x4a\x5f\x05\xb5\xc8\x6a\x2d\xde\xd3\x00\x10\xc7\x47\xd1\xda\x04\x03\x90\x5a\x45\x08\x3c\xa9\xd4\x24\xf1\xe8\xd9\x2f\xee\x87\xd3\x53\x4c\x12\xa1\x6b\x7d\x68\xe0\x01\x2f\x2d\x1e\xf0\x46\x6b\x20\xaf\x92\xb2\x74\x5e\xf1\x04\x0d\x67\xce\x78\xe2\x1a\xc5\x1e\x6a\x54\xf0\x84\x4d\x51\xce\xc5\x21\xa0\x9f\x97\x2f\xdc\x2a\xb9\xbc\x94\x1f\x9f\x34\x7c\xbc\x2f\x3f\xde\x6b\xf8\x58\xdf\xb2\xa1\xa2\x38\x1f\x62\x7d\x91\x09\xce\x8c\x3c\x4d\x86\x2b\xe7\xf0\xd3\x92\xfc\x76\x5c\x60\xef\xa4\xc0\xbf\x04\xae\x77\x78\xbb\x3b\xd0\xe2\xf8\xcc\xdb\x39\x9f\xec\x20\xe1\x44\x2c\xf7\xb0\xd4\x19\x2e\x07\x51\x84\xd2\xdc\x6a\x3e\xa1\x11\xf1\xb3\x46\xc4\x67\xa4\x84\xbf\x0b\x07\x71\xc1\x7c\x63\x77\x8f\xec\xee\xca\xb2\x71\x37\x4b\xe0\xe6\x1f\x02\xe6\xe6\xc8\xf8\x6c\xb0\x80\xe7\x26\x29\xd8\x73\x6f\x4f\x76\x8d\x43\x7e\xac\x0a\x1b\x50\x88\xa6\x48\xca\xb4\x97\xa2\xcf\x9e\x63\x6e\x68\x69\x5d\x51\x4e\xea\x74\x18\x84\x94\x8d\x5a\xe4\xe2\x8c\xc6\xc9\x28\xdd\x0b\xfd\x70\x82\x35\x41\x99\xc2\xdd\x90\x6c\x94\x8f\x7b\x13\x3f\x04\x65\xc1\xca\xe9\x18\x76\xfa\xd2\x49\x14\x2a\x6f\x91\xd6\xc4\x70\x43\x08\xa3\x3d\xe8\x60\xb8\x86\xf5\x8f\x6b\x60\x6d\x84\xd3\x38\xc4\x70\xe8\xd4\x76\xe3\x0d\xa8\x15\x68\x9d\x61\x3a\x02\x51\xe9\x7f\x82\xee\xb3\x51\x41\x03\x80\xc6\x0a\xdc\x05\x5a\xbb\x75\x70\xd3\x6c\x03\xbc\x6f\x65\xf2\x3d\x93\x16\xee\xc9\x3c\x7c\x46\xc1\xdf\x2c\xfd\xf8\x77\xeb\xe9\x9d\xf5\xf4\x8d\xca\x97\x56\x70\x4d\xb1\xd8\xa5\xad\x3c\xb6\xab\xf3\xae\xed\xf2\x05\x8a\x0c\x87\x59\x5b\x63\x8d\xb2\x9a\xc8\xee\xf9\xbc\x51\x92\x33\xf9\x55\xf4\xa8\x4a\x53\x42\x1c\x66\x3c\x7d\x21\x34\xeb\xcd\xbb\xcd\x5d\xf6\x71\x15\xc6\xf9\x06\x78\xe4\x47\x59\xcc\x61\xee\x68\xb7\x87\x8a\x8e\x42\xd1\x2f\xb6\xc6\x3e\xfa\x13\x75\x55\x0f\xac\xe2\xab\x56\xcb\x2f\xd6\xae\xff\xab\x25\xee\xfe\xd4\x44\x25\xaa\xd8\x3c\x96\xa1\x88\x23\x35\x25\x83\x52\x2f\xe0\x19\x94\xe3\xa5\xa6\x24\xb3\x26\xb6\x85\xde\x6e\xcc\xcd\xed\xfa\x7f\x55\xea\x3e\xfe\x82\xba\xc6\x3a\xff\xd5\x58\xe7\x35\xf6\x8f\x7a\x00\xb5\xf9\x2b\x0a\x5d\xb4\xd1\x1d\xec\x18\xbe\x3c\xb6\xbe\x3c\x85\x1f\x20\x9e\x75\xab\x7f\xd9\x9a\x11\x98\x43\xa6\xed\x17\x08\x99\x6b\xca\x7d\xb3\x80\x81\xbf\xa2\x30\x5b\x1a\x0e\x87\xfd\x76\xbf\xf7\xc3\xad\x1f\x6e\xf7\x7f\x3c\xb8\x5d\xde\x3a\x38\xe8\x1f\x1c\xdc\xb9\xfd\x43\xbf\x6d\xda\x93\x85\xd8\x44\x2f\x88\x2b\x94\x65\x93\x9e\xa1\x1c\xb9\xd7\x93\x6e\x85\x34\xb7\xb6\x6a\x35\x4b\x25\x7b\xf2\x55\x7f\x20\x14\x4f\xd1\x01\x75\xac\x54\x46\x1d\xa1\xde\x2b\x0b\x32\x5b\x13\x4e\xed\x4e\xf2\xef\xe0\xf6\xc1\x4f\xb7\x7f\xfa\xfe\x87\x83\x9f\xee\x7c\x87\x1a\xca\x50\x3f\x0f\xdc\x62\xdf\xf8\xec\x41\x61\x1d\xb7\x83\xf9\x3f\xe5\x5a\x50\x39\x71\xd1\xd0\x92\x2e\xab\x67\xc9\x28\xa1\x58\xdd\x8c\xfe\x6f\x44\x03\xc6\xfc\xdd\x4f\x67\x58\x4b\xfe\x84\xb9\x8e\x0a\x8b\xcc\xa9\x15\x21\xcc\x3e\x24\xc6\x05\x06\xda\xbc\xa3\x73\x25\xd4\x8f\xf7\x04\xf7\x47\xee\xe1\x16\xdf\x13\x4c\xf7\xf8\x21\xa1\x6d\xd4\x27\x49\xa7\xe3\x7d\xe0\x19\xf8\x30\xbd\xa9\xb6\xef\x0b\x2b\x7f\x0c\xd4\x48\xd0\x4a\x57\xe9\x53\xb8\x63\x2d\xb8\xd5\xff\x0e\x2c\x4a\x8a\x8b\x41\x20\xef\xe1\xe8\xcb\x9e\x81\x0c\xd3\x4e\x8d\x34\xc0\x38\x0f\x2f\x12\x02\xef\x69\x82\xc1\x4b\x08\xa2\x32\x91\x99\x9a\x52\x2a\x08\xd3\x37\x3e\x4b\x26\xe6\x77\xf3\xf3\xee\xe3\x44\x84\x2b\x90\xdf\x83\xf2\x76\x3d\xce\x0f\x61\x96\xb9\x40\x46\xd6\xd2\xf4\x7e\x5b\x9b\x2c\x48\xab\x20\x29\x71\x4d\x9f\x3b\x9d\x07\x89\xa7\x57\x45\xfb\x01\x0e\xe6\x01\xe0\xc8\xf5\x5e\x24\x2e\x8c\x29\x67\xdc\x71\xa3\x4f\x9d\xc8\xa6\x5e\x43\xd1\xd7\xe8\x5d\xe1\xf2\xb3\xe6\xf5\x7a\x96\x26\x7b\x14\xee\xc7\xf7\x53\xb9\xce\x90\xef\x84\x19\x23\xff\x17\xf0\x9e\xf4\x02\x74\x89\x30\x47\xa5\x22\xef\xf2\xed\x34\xc0\x81\xd0\xa9\xb9\xc3\x49\x25\x30\x2b\xbc\xb3\xc4\xbb\x62\x6a\xd4\x94\x0c\x3c\x4d\xe6\xd1\xc9\x4a\x3d\x5f\x64\x51\x21\x7f\x73\x33\x92\x19\x67\x7d\x14\xe0\x5f\x86\xde\x2a\x83\x31\x7c\x52\x4d\xc5\xdd\x0d\xad\x6c\x08\xda\xbc\x79\xc3\x1b\x52\xc1\x7a\x9b\x89\x22\x60\x95\x49\xa3\xa1\xe0\x7e\x37\x0a\xfd\xfa\x84\xbd\x49\x48\xef\x2b\x52\x4c\x59\xba\x13\xc2\x2c\xc1\x04\xaa\x16\x77\x64\x37\x3b\xe8\xc0\xe2\x73\x84\x57\x9b\xf0\x9e\xd6\xeb\xba\x1a\x98\x2a\x5e\x8a\xb8\x95\xfd\x0e\x7b\x32\x06\xc6\x80\x45\x46\xbf\x28\x0d\x66\x95\x60\x06\x83\xc7\x0f\x78\x54\xcb\x4f\xfa\x83\xbc\xda\x40\xe4\x3d\xc1\x96\x2b\xaf\x54\x5d\xc3\x6b\x10\x16\x3a\x9b\x6b\x51\x1b\xb9\xb9\xb8\xe9\x6c\xc0\x15\x96\x07\x4a\xe9\xef\xf7\x3c\x79\xb3\x0b\x8c\x1d\xd8\xc8\x82\xa6\x6d\x27\x14\x6e\x8b\xa8\x38\xdd\x09\x31\xe7\x1e\xd0\x2a\xa8\x5c\x3b\x68\x9c\x75\x4d\xfd\x69\x55\x18\x3b\x0f\xa4\x95\x29\xf3\x6c\x95\xb3\xdf\xaa\xa6\x61\xd5\xbc\x9b\x16\xb6\x7d\x57\xb1\x0a\xed\xc2\xf1\x97\x14\x5e\x7e\x49\xe1\xb9\xc1\xa2\xcf\x0a\xd3\x53\xa2\x2a\x33\xb3\x26\x3c\xcd\xe3\x68\xd9\x44\xf4\x6b\x0f\xf7\x5a\x71\x13\xc0\x5a\x13\xf2\xc4\x8c\xf8\x64\x10\xbb\xd1\xd7\xa6\x36\x65\x2d\xcc\x84\xce\xb0\x03\x10\x36\xd6\x75\x0a\xaa\x60\x94\x4c\xe3\x15\x26\xbf\xc2\xa3\x1a\x4c\x3d\x36\x17\x86\x56\x44\x39\xd2\xa1\x5f\xb2\x7c\x15\x17\xc1\x33\x1c\x6b\xcd\x1e\x68\xcc\xa3\x4d\x7b\xb3\x75\x1b\x42\x6b\x59\x85\x79\xf2\x09\x74\x2e\xf4\xe3\xd3\x6d\x0e\x6b\xd4\xd6\x8d\x7e\xb4\x22\x5f\xe9\x88\x98\x78\x10\x1c\xea\x3e\x8d\x3a\x54\xe4\x1a\x33\x23\x23\x97\x98\x23\x62\x19\xba\xe8\x70\xd3\xb3\x41\x4c\x14\xac\x8c\x81\xfe\xa9\xde\x82\x0d\xa5\x7f\x02\x03\x50\x13\xdc\x68\x87\x10\x94\xc7\xc9\xe8\x28\xf1\x8f\x13\x3e\x38\xc3\x05\x5b\xd8\x67\x83\x2d\x12\xcb\x2c\xc2\xca\x36\xcf\xad\x9c\xae\x0c\xe5\xb0\x2e\x92\x79\xca\xfe\x2a\x48\x42\x67\xde\x5c\x63\x25\x05\xb0\xe6\xc9\x28\xf2\xd5\xf1\xdf\x14\x34\xdd\x82\x9a\xd9\x32\xc9\x66\xa3\xd7\x4f\x72\xe4\x85\x0a\x4e\xc0\x84\xec\x89\x7f\xc0\x43\xc1\x72\xd2\x23\xab\xdf\xa6\x49\xb7\x46\x63\xa0\xf7\x30\x81\x0f\x5b\xa7\x3a\x0a\x52\x63\xaa\x23\x3e\xd3\xa2\x42\x24\x12\x8a\x47\x7c\x42\xbd\x3c\x08\x71\xd6\xc5\xd7\x4f\xd0\x6b\xee\x29\xb0\x43\x9c\xfa\x1c\x70\x84\xe0\xba\x96\x1b\x77\x56\x98\x09\x32\xad\x69\x4c\x14\xa7\x48\xac\x09\x4d\x9a\xb8\x81\x66\x16\x05\x2d\x7a\xca\x90\x59\x5d\xfd\x9c\x48\xe7\x36\x3b\xda\xd2\x18\x35\xc0\x59\x84\xeb\x25\x36\x91\x98\xe6\x0e\xa7\x12\x36\x4a\xfc\xbd\xfe\x1e\x5d\x95\xe5\x25\x36\xd5\x25\x55\xaa\x13\x65\xa9\xe4\x76\x9e\x62\x31\xa0\xa4\xca\x58\x12\x4d\x3f\xff\x04\x43\x29\xf8\x4d\x5f\xde\x2e\x87\x4c\x93\x4b\xa5\xf1\xc6\xf5\x2a\x6a\x19\xdb\x1c\x45\xd5\xc9\x61\xaf\x53\x98\xa4\xc8\xc6\x93\xe1\x0d\xa9\x2d\xbc\x68\x17\x17\x5e\xbb\xbd\xbb\xab\x08\x2b\x12\x2b\x2f\xfa\xa2\x05\x2c\xda\xa9\xac\xdf\x51\x8a\xe7\xbc\xa1\xa9\x2d\x8b\x18\x17\x9e\xc8\x2f\x48\x5a\x55\xae\x7d\x32\x1b\x90\x9b\x7a\x2b\x8d\x5e\xbd\x8c\xf1\xf5\xc8\xc9\xc1\x04\xc1\x0d\xc4\x0c\xfa\xce\xd1\xc5\xe3\x2a\x9f\x16\x74\xe4\xe5\x6b\x03\x9a\xa6\xa5\x6d\x82\x53\x59\xda\x58\x7d\x8b\xc3\x88\x02\x64\x06\x12\x49\xa1\xb1\xcc\x53\x6b\x99\xa7\x03\x91\x4c\x5a\x2c\xf3\x69\xb0\xc2\xac\x98\x31\xfc\xe9\x73\xdf\x98\x1c\x53\xec\x4d\x3d\x6d\x90\x7e\x02\xd8\xb2\xd1\xd4\xc7\x11\xc6\x18\x46\x8b\xcb\x3e\x32\x36\xb6\x2a\xfc\xfb\x03\xf4\xde\x0d\xf3\xa7\x7c\x93\xd8\x3c\x4b\xd2\x80\x55\x1a\x76\xd6\x5d\x2d\x67\x7c\x03\x58\x11\x43\x8a\x2c\xa6\xd7\x74\x05\x59\xd1\xe9\xaf\x5d\xba\x4d\x2b\xcc\xd5\x5e\xb4\xe9\xd0\x3f\xa9\x00\x84\xdb\x01\x5e\x14\x38\xb8\xf7\x35\xba\x40\x1b\x14\x41\xb4\x61\x6c\x04\x2e\x45\xce\x1d\xd5\x80\xc3\x2c\x0e\xd0\x62\x13\x68\x68\xd3\x8f\x51\x34\x52\x5c\x46\x36\x1a\x87\x5e\x3a\xf1\x53\x7e\x90\x82\x87\x33\xa6\xc1\x03\x73\xe1\x44\xb6\xe7\x45\x73\x8b\xd7\x38\x8a\x14\xc3\x12\xd7\xe6\x0e\x60\x6d\x19\x72\x4e\x8a\xf3\xb7\xa2\x3c\x13\x91\x9a\xb8\x42\xf4\x37\x85\xf7\x11\xd2\x10\x61\x96\x53\x06\xac\x9b\xb4\x2c\x73\xf8\xa3\x82\xd8\xb0\x69\xb9\xcd\x63\xb2\x26\xf4\xa9\x51\x87\xd4\xdc\xd2\x9b\x07\xf9\x5e\x3a\x98\xa3\xe8\x84\x45\xbf\x0c\x7a\xc3\xf9\xa8\xe7\xcf\xf9\xe7\x53\x9b\x2d\x9c\x72\x6e\xbf\xf4\x76\x81\x41\x7c\xa0\xdd\xd1\xe5\x30\xe8\x41\xbd\x53\x7b\x99\x5b\xa7\xc0\x83\x50\x25\x1c\x61\x54\x7a\x39\x44\x27\x02\x31\xe6\x0e\x26\x2a\xf5\x13\x98\xff\xd3\x1b\xe9\x61\x3c\x43\xbb\x8c\x91\x5b\x5a\x5e\x96\xc4\x8c\xdf\xb3\x87\x6c\x90\x03\xa9\x51\x7c\x65\xf6\x00\x89\x18\xe6\x72\x2d\xab\xd0\x83\xc9\xf1\x16\xa7\x20\xec\x74\xee\xa6\xee\x88\x33\x04\xdf\x59\xc1\x52\x62\xc4\x2c\x12\x7f\x05\xcc\x22\x72\xc5\x2d\x5e\xab\x5d\x84\x11\x06\xb7\x5a\x1b\xe3\xdb\xa6\xff\xa1\x49\x0b\x12\xf2\x26\x43\x91\x2a\xa1\xd8\xbc\xe5\x15\x6b\x1a\xa3\xc7\x87\x79\x0d\xbf\xa1\x01\x0d\xdc\xc8\xe0\x36\x9d\x4e\x3e\x54\xf8\xbd\x10\x37\x1b\x15\x81\x2a\x22\x25\x45\x59\x0a\x6d\xb0\xf0\xf1\xc7\x51\x32\x42\x87\x36\xf2\x4c\x79\x67\x17\x77\x71\xe3\x1b\x53\xdd\x24\x75\xc3\xd8\x36\x3b\xda\xae\x37\x7e\x81\xfe\x46\x5e\xfa\x9b\x90\x02\x56\x94\xa4\x70\xad\xd6\x97\x37\x09\x0b\x7c\xdd\x6e\x77\x3a\x61\xbb\x9d\xf1\xdc\x34\x38\xdb\xe1\x97\x28\x7e\x5f\x00\x31\x9e\xb8\xd0\x20\xd7\x55\x46\x22\xe7\x8d\x13\x4d\x37\xa2\xd6\x27\xd4\x94\x30\x85\x25\x61\x8a\x81\x64\x49\x5c\xc2\xac\x82\x08\x25\xcc\x14\xfe\xf4\x27\x83\x2a\x32\xa6\xde\x0a\x46\x3f\xca\xc8\x80\x01\x62\x40\x45\x73\x45\x92\xc7\x87\x15\x83\x0e\x1d\xca\xc9\x6e\xa9\x98\xc7\xdb\xb5\x90\x2f\x11\xf8\xd6\xc5\xae\x5b\x67\x1d\x2b\x8a\xeb\x44\x6f\xb4\xf8\x53\x6f\x5a\x59\xfe\x96\xb6\x30\x75\x6d\x46\x20\xb5\x86\x15\xd7\x1a\xf8\xe2\xbf\xb9\xb2\xf0\x05\x43\x81\x69\x37\xc6\xd2\xa0\x66\xac\xe8\x88\xc4\x75\x9b\x53\x30\x86\x78\x30\x4b\xb9\x9f\x3c\x17\xd4\xe0\xd9\xa4\x00\xab\x3c\x92\xab\x3c\x92\xab\x3c\xf2\xa6\x30\x5e\x73\x95\xf3\x37\xd6\x2a\x1f\xc8\x8c\xd6\xf4\x6e\x90\x06\x4b\xae\xa5\x2c\xf1\xf3\x0a\xd0\xb9\x0a\x0c\x45\x25\x25\x94\x5d\x9c\x46\x20\xc5\x57\x9a\x0e\x34\x4d\xa1\x26\x11\x0b\xe6\x61\x28\x2d\x87\x96\xad\x42\x1a\x42\x16\x60\x48\xae\x88\x70\xad\xee\x88\x54\xc2\x88\xe8\x90\x49\x40\x67\x43\xfd\x22\x48\x46\xb8\x13\xee\xff\xec\xd4\xb6\x41\x0a\x1f\x23\x81\x51\xfa\x77\xe7\x51\x8c\xc9\x89\x1a\x5a\xe4\x5e\x49\xf2\xb9\xb8\x52\x50\xa9\x33\x6c\x6a\x69\xc1\x87\xbe\xf9\x41\xd0\x7f\x86\xa6\x1a\xb2\x03\xbe\xa1\x00\x80\x61\x06\x70\x1e\xf6\xd3\x6e\x5f\x3a\x5a\x1d\x88\xd6\x9c\x81\xf0\xed\xd8\x4c\xdb\x66\xa3\x14\x74\x42\x2b\xf0\xe3\x92\x76\x95\x1d\xfe\x5e\x46\x4c\xe0\x3d\xbc\x29\x98\x51\x61\x51\xb0\xc4\xc1\x43\xc5\x29\x97\xee\x78\x21\xe9\x6c\x35\xb5\xd6\x00\xf7\xb6\x69\xa7\xab\xba\xa8\x58\x69\x2b\x3a\x94\x4c\x8d\xb1\x93\xac\xd7\x1e\xb6\x6b\xc4\x1c\xfd\x3d\x26\xaf\xbd\x91\xd0\xcc\x8a\x37\x32\xe5\x6b\x66\x13\xdf\x56\x31\x26\xbb\x0c\x24\xd5\x70\x05\x58\xa4\x29\xa7\x16\x3a\x7d\xd7\xa7\x78\xf3\x51\xe4\x83\x08\x84\xb5\x1c\x70\xc1\x8d\x1c\x0b\x20\xdf\xcd\xc9\x8c\x37\xb4\x05\x75\x74\x05\xeb\xf7\xbe\x90\xd5\x57\x19\x39\xc8\x66\xba\x3a\xe6\x1a\xe1\x9c\x0e\xa4\x7f\x27\xad\xf1\x6a\xee\xae\x17\xf7\xca\xc8\x45\x06\x5f\x39\x1b\xa6\xe5\x85\xf6\x00\x68\x5e\x60\x9d\x39\x32\xeb\xfc\x5d\x4c\x0c\xb3\xbb\x80\x25\xa6\x52\x83\x09\x8e\x8d\x56\xc1\x0a\x97\xad\xb8\x7a\x27\x45\x32\x59\x55\x01\xe7\x47\x01\xd1\x3a\x59\xa6\x68\x85\x6b\xa1\x52\x61\xf0\x17\x95\xf9\xb6\x74\x65\xad\x9e\x5a\x6b\x93\xdb\x10\x35\x07\x0b\xb7\x21\x5c\x5c\x7a\x9a\x66\x8d\x50\xb2\x6d\xde\x0a\xc3\x47\xd1\x6e\x1f\x7c\xc7\x7f\xe1\xf1\x9c\x6d\x14\x67\x2a\xe5\x74\xe2\xf0\x5a\x49\x91\x69\x62\x03\x6d\x1c\x95\xba\x14\x05\x02\xd7\x06\xf1\xdc\x0f\x4a\x13\xfd\x66\xf0\x1f\xff\x01\xc8\xa2\x9b\xd9\x92\xad\x34\xa4\x21\xf1\x2a\x54\x74\x8c\x9f\xb6\xc6\x1f\x48\x80\xa2\xb2\x0c\xff\xeb\x00\x03\x40\xb5\xef\xc8\x13\x8e\x23\xa4\xfe\xff\x3a\x00\x8e\x9e\x78\xb8\x0a\x18\xb2\x72\xfe\x53\xfa\x90\xb8\x73\xc8\xf0\x1f\xbc\x54\x13\xcb\x2f\x3e\xbc\x57\xc8\xd3\x5d\xc2\x3c\xeb\x11\xa8\x8d\x13\xcc\x34\xa2\xc6\x19\x34\x12\x41\x47\xc9\x88\xde\xa3\x18\x61\x93\x35\x6e\x25\x73\xa6\xab\x5d\x03\xdd\x3c\xcd\x8a\x8d\xce\x11\xbc\x09\x22\x81\xff\x30\xf5\xd3\xf8\x60\xb2\x97\xc0\x7f\x48\x2a\x69\x76\x08\xc8\x04\xd3\xcd\x66\x66\xa9\x3e\x3e\x11\x1c\xac\xfd\xfa\xc7\x00\xc3\x30\xd0\x2a\x1d\x3d\x86\x35\xe0\x8b\x4d\x70\xf8\xf5\x00\xfe\x33\x62\x0e\x15\x1a\xd0\xe0\x96\x98\x30\x7c\x3c\xd7\x63\x00\x6a\x8b\x91\x23\xc0\x75\xd6\xab\x87\xf9\xb4\xc0\x10\x03\x94\x9b\x09\x2e\x69\xbc\x0f\x7e\x6d\x7a\x6c\x50\x76\x68\x77\xed\xf5\x2d\xc1\x0b\xde\x86\x11\x16\x59\x59\xaf\x05\x5d\x46\x26\xfb\x20\x49\x06\x64\xcc\x8f\x18\xe9\x7d\xa8\x44\xed\x81\xe3\x2f\x92\x01\x65\x99\x0d\xcd\x00\xc9\x1b\x38\x85\xb9\x20\x4b\x36\x4a\x6a\x29\x53\x29\x2e\xd8\x35\x5d\xba\x95\xc3\x35\xb5\x1b\xbe\xec\x05\xc3\x78\x70\xf7\xae\x93\x28\x7f\xb9\x4b\xeb\x00\xac\x27\x27\x91\x04\x8f\x7a\x0c\x6e\x58\xf0\x95\xaa\x55\x91\xeb\xf8\x7d\xa1\xb9\x46\xb2\x71\x24\x01\x06\x32\x7b\xaf\x80\x2c\x8d\xed\x0e\x1f\xb5\x1a\x71\x13\xb1\x71\x44\xb2\x49\x67\x53\x47\x87\x42\x20\xb9\x24\x88\x36\xa3\x8c\x8f\x0f\x6d\x12\xba\xdd\x66\xc1\x9a\x8b\xe1\xf0\xf1\x2e\xd1\x50\x44\x24\x71\x3e\xc5\xcc\x83\x23\x9b\x47\xc3\x51\x06\xd5\xab\xdc\xff\x75\x61\xc5\xc8\xa0\xc3\x60\x84\xc9\xb4\x8c\x7d\x52\x6b\xbb\xee\xb1\xda\x63\xdc\x95\x91\x21\x8e\xca\x76\xb0\x29\xd6\x6d\xfc\x9b\xb7\xf3\x76\xb2\x53\xac\x96\x31\xe3\x41\x6c\x46\xf8\xaa\x19\x34\x82\x9b\x81\x44\x42\x80\x64\x3b\x12\xd5\x2c\x45\xc1\xa6\xa7\x7c\xc1\xcf\xfc\x73\x23\xae\xd4\x2c\x65\x1f\x74\x70\xa8\xd2\x63\xc1\x25\xfc\x07\xae\x71\xf0\xc1\x88\x34\x2d\x2a\xdb\xc5\x44\x45\xa6\x6e\x3f\x72\x9a\xdf\xcb\x0c\x2a\x5c\x8c\xe9\x22\xe4\x73\x27\x2a\xf5\x5f\x9b\xa7\x2b\x74\x4d\x23\xff\x80\x11\xa0\x6a\x4f\x4b\x31\x64\xa3\xbe\xcf\x86\xc5\x68\xaf\xef\x1b\x6b\xf6\x89\xb1\x4f\xf8\x4a\x47\x1e\x92\x1d\xf9\xfc\xfa\x79\xd1\xa1\x87\xa0\x3c\x21\x2f\xdf\x8b\xa3\x33\x31\x43\x03\x6c\x11\xd7\x80\xdb\xb0\xd3\xfc\xc1\x44\x74\x63\x64\xf0\x3b\x8c\x3e\x7a\x53\x70\x8d\x1c\x1f\xba\xb8\x77\x8b\xde\x3f\x6c\x20\xb7\xdc\x6f\x5c\x1f\x40\xd5\x7e\x90\xe3\xf2\xe6\x04\x90\x28\xc9\xd0\x2c\x50\x28\x52\x22\xe1\x76\x86\x19\x48\x6b\x80\xa6\x62\x6d\xdf\x58\xb1\xb6\x0f\xcd\x3d\xe2\xf4\x22\x61\xd9\xe3\x07\x72\x3b\x56\x04\xa2\x9a\x67\xd4\x7e\x56\x8c\xb1\xa9\xc2\x71\x54\xc0\xa2\x93\x9b\xca\xb8\xc1\x9e\x07\x86\x10\x7e\xb4\xb5\xf2\x94\xce\x1d\x6e\xaa\xfb\x79\x6b\xdd\x33\x76\x89\x59\xd3\x64\x6d\x09\xb8\x51\xff\xe3\x97\xd6\xbf\x34\x6b\xff\x61\xd7\x3e\xa2\xd3\x43\xa2\xf0\x91\xdc\xf6\x49\xc4\x73\x5e\x84\xd3\x33\xd4\x7b\xb2\x34\x2d\xda\xed\xdf\x70\x1d\xd3\x6f\x33\x06\xd2\xa6\x69\x3a\xdb\x80\x86\x26\xa3\x68\x4a\x55\xec\x37\xab\xd8\x15\x62\xc5\x2f\xf8\xbd\xb5\x7e\xcf\x3b\x3a\x5a\x42\xdf\x3e\x33\x62\x0d\x7e\xaf\x79\x28\xec\xa5\xff\xd0\xd8\x04\x11\xeb\x13\x8d\x7d\x84\x0e\xc6\x83\x66\xbf\xc4\x4c\x42\x4f\x18\x39\x15\x64\xf4\x33\x44\x03\x12\xd3\x18\xf4\x4d\x4b\xf6\x9d\xc1\x25\x7e\xc6\x60\xed\x9f\x93\x00\x80\xe8\x99\x81\xda\xdf\x14\x62\x37\x48\x2a\x85\xdc\x1e\xe0\x38\x91\x57\x64\x39\xa7\x09\x3a\x84\x98\x33\x4b\xf8\x26\x61\xf0\x8b\x42\x9c\x57\x68\xc0\xbc\x9e\x34\xe1\x31\x2c\x10\x6f\xb1\x02\xb3\x87\xb3\x74\x6d\xad\xa6\x42\x7b\xee\x80\x09\x41\x9f\xc8\xcf\x33\x4f\x90\x65\x00\xd3\xe0\x06\xc1\x95\xb0\x3b\xe6\x89\x59\xb1\x8f\x99\x54\x81\x47\x3c\xa4\xde\x55\xaf\xe3\x31\x74\x37\x99\x58\xfb\xcb\xe2\xdb\x48\x1e\x9a\x4a\x3d\x01\x6f\x10\x11\xc4\x84\x3c\xe9\x6f\x30\x31\x48\xee\x87\x68\x04\x78\x4a\x41\x55\x25\x96\x60\x04\x6a\xf2\x29\x34\x12\x36\x6b\xd6\x07\xf2\x57\x6e\x07\x58\x05\xfc\x90\x0f\xaf\xf0\x9d\x04\xac\x24\x50\xd1\x00\x2d\x38\x8a\x8f\xa8\x39\x45\xde\x18\x0a\x5a\xb1\xf3\x7f\x5a\xe1\x89\x95\x20\xc7\x8f\x05\xc6\xfa\xdb\xef\x3e\x1b\x71\x8a\xbf\x2a\x22\x43\x63\x91\xe6\x52\x2e\x20\x50\xb8\x5c\x43\x13\xf8\x5c\x10\xa0\x63\x71\x1a\xc2\x8b\x26\x62\x17\x02\xe4\x3b\x39\x1a\x00\x64\x59\xd7\x57\xbf\x86\xc3\x61\xe2\xb6\x97\x09\x90\x83\x28\x94\xf9\x99\x7a\xb9\x0a\x70\xb0\xf9\x68\x2c\xc1\xe8\x4c\x39\x24\x13\xdf\xe1\xee\x85\x8f\xbc\x57\x74\x30\x0e\xc3\xd1\xb8\xc0\x4d\x10\xc0\x40\x31\xb1\x36\xa9\x7f\xc6\x52\xfd\xbb\x77\xc3\x12\xfe\x43\x24\x1a\x51\xa0\x72\x80\x30\xbc\x82\x12\x9e\x61\x85\x4c\x5f\xa4\xac\xfa\x81\x62\x18\xae\xe7\x01\x75\xc0\xd8\xc8\xb2\x09\xef\xca\x33\x16\x66\x1c\x38\x1b\x87\x93\x01\x7a\x30\xc4\xfc\x15\x9a\x8e\x73\xba\x1d\x8e\x16\xbe\x34\x1e\x8c\x38\x52\xa6\x17\xb4\xec\x9d\x5b\x2b\xa8\x77\x59\x47\x00\xc1\x30\xc7\xec\x35\xde\x54\x1d\xf2\x18\x4c\x87\xf9\x80\x4c\xe4\xbb\x77\x03\x61\x76\xc7\x00\x4a\x3e\x19\x28\xff\x47\xdc\x6e\xe3\x3e\x0c\xed\xa0\x96\xc1\xca\x0b\xc7\xa0\x4a\x4d\x82\x58\xdf\x51\xc6\x71\xc5\x03\x06\x8c\x60\x55\x66\x12\x81\x46\x8c\x0d\x56\xcc\xe1\x1a\x90\xa7\x85\x40\x49\x60\x22\x01\x96\x10\x13\x3a\xf4\xdb\xc9\x88\x51\x7f\xf2\x08\x85\xd4\x13\xc7\xd9\x04\x16\x11\xb6\x43\x42\x23\xed\xf4\xad\xce\x13\xa6\x4e\x8c\x8b\x8e\xd5\xc5\xd6\xd1\x5d\x75\x5a\x3f\x92\xe8\x87\xe9\xc2\x3b\xdc\xc2\x00\x1d\x04\x83\x05\xfc\x07\x93\x1a\x06\xe1\x26\x15\xf1\x17\xd4\xb7\xf4\xc5\xd7\xa1\xc2\x45\xc4\xfb\x35\x03\x7d\x33\xf3\x14\xa8\xb9\x3f\x62\xec\xea\xd3\x99\xae\x05\xcb\x4e\xd8\x03\xc6\x96\x7f\x44\x78\x64\x1d\x6f\x66\x1b\x55\xde\x92\x50\xf7\x61\x95\x8b\xfa\x7e\x62\xb0\xf6\x48\x8d\x59\x4e\x0c\xa8\xc8\x37\x73\xeb\x79\x3d\x33\xeb\x45\xe1\xeb\x6f\xb8\xd0\x15\x23\x2b\x4b\x3c\xbe\xad\xcb\x6d\x52\x53\x0a\x13\xed\x4c\x9b\xaa\x34\x64\xc5\xa1\x70\xa7\xbc\x79\x97\x92\x58\x55\xe2\xab\x18\x01\xd7\xb0\x68\xb9\x90\x15\xfa\x0c\xc6\x29\x34\xcc\x29\x4e\xa6\x36\x95\xa1\x7e\x45\x47\xa7\x8b\xca\x8d\x50\x40\x56\x95\x89\x1c\x04\x58\x43\xac\xbe\x5d\x2d\xe4\x51\x84\xa6\x26\xde\xfa\x07\xb3\x2f\xa9\x32\xc7\x34\x17\x80\xbe\x7c\x1d\x16\xb0\x58\x4a\x0a\x00\x04\x48\xbd\x96\xc8\xf9\x8b\xc1\xa4\x2f\xc2\xe2\x54\xa4\x8e\x31\x37\xbb\xa3\xd1\x1c\x1a\xa4\x4d\xc4\x15\x86\x10\x78\x71\x00\x70\x4d\xe5\xde\xa6\xe8\x01\x75\xc7\x29\xf4\x10\x0b\x76\x2e\xce\x99\x03\x4b\xf7\x9d\x88\xeb\x91\x85\x4b\xc8\x59\x79\xb1\x31\xc4\xd0\x3a\x8a\xbc\x17\x14\x14\x6f\x7e\xfb\x56\xff\xfb\x3b\x77\x7e\xf8\xfe\x8e\x57\x04\xce\x8f\x77\x7e\xfc\xe9\xa7\x5b\xb7\xef\xfc\xd4\x2e\xdc\x8e\x03\x05\x0e\xda\xea\x15\x25\x20\xa4\x97\xb7\xdd\xf6\xc1\x9d\x83\xef\x6f\xdf\xe9\xdf\x82\x5a\x1d\x6c\xe8\x47\xf1\xb7\xff\xbd\xd7\x3f\xf8\xc1\x8c\x57\xcf\x2b\x88\x4d\x83\x0c\xfd\xed\x86\xa9\x4c\xae\x89\xc4\xf4\xa8\xae\xea\x93\x21\xa6\xb6\x43\x87\x31\x80\x0f\xb1\x0e\x7a\x9a\xf5\x06\x13\x6f\xa3\xa8\x30\x5f\xce\x5f\x22\xbd\x61\x18\x71\x5e\xe7\xe6\x14\x2a\xee\xa4\xc8\x60\x12\xf8\xba\xd7\x77\x7d\x7a\x28\xc6\x79\x47\x1f\x68\x31\x60\x9a\xaa\x95\x25\xbd\x20\xf2\xa8\x0c\x6d\xd3\x02\x44\xa6\x5c\x2b\xb8\x13\xd1\x00\x28\x32\x73\x88\x49\x93\x18\x53\x81\xf1\x93\x40\xa1\x88\x22\x07\xdd\x02\x4c\x79\x90\x03\x00\x49\xd8\x49\x15\x24\x86\x36\x15\x33\x6d\xc3\x9c\x33\x4e\x97\xdb\x0e\x01\x90\xef\x74\x89\x95\xec\x4d\xb0\x24\x98\xf1\x3d\x05\x6e\x40\x58\x0e\x11\x30\x69\x9d\x1c\x33\x61\x78\x19\xe6\xb1\x8a\x93\x61\x36\x9a\x61\xde\xc5\xcc\x03\x41\xca\x6d\x67\x18\xce\x9c\xe1\xc5\xc0\xd2\xad\x85\x67\x2f\xb6\xb0\x03\x5a\x06\xaf\xa0\x27\x6c\xb6\xc1\x58\xb1\x23\x7d\xd4\xe2\x46\x26\x6b\x44\x85\xb2\x06\x6b\xe5\x0f\xcb\x5a\x99\x33\xc3\x5a\xb1\x8e\x4b\x4a\xb5\xd5\x8c\xec\x63\xb5\x2c\x52\x36\x03\xe5\xa7\xb7\x79\xb6\x17\x3f\x12\x1f\x0d\xce\xce\x6d\x2c\x4e\x13\x09\xe9\x1c\xab\x76\x7b\xc5\xfb\xf5\x69\xf1\xd3\x4f\x54\x18\x87\xe9\xa8\xe7\xa7\x7b\x09\xac\xf4\x70\x4f\xb9\x3b\xa6\xc3\x18\x7d\xda\xd3\x00\xc5\xa0\xbd\xb5\x89\x1b\x26\x53\x39\x69\xbf\x27\x62\x73\x93\x8d\xf6\xf6\xa6\x3e\xf0\x38\xcb\x4d\x56\x4c\x4c\x31\x80\x2e\x1b\xe9\xa4\xc7\x4c\x21\x06\x20\xc0\x66\x04\x20\xd1\x70\x98\x01\x8b\x71\x42\xfa\xe5\x76\x94\x7f\x26\xe6\x20\xc5\x55\x90\x64\x18\x0f\x80\x96\xab\xbc\x29\xc2\x73\x0f\x42\xe1\x77\x43\x47\xe6\x59\x4f\x30\x84\x7f\x0a\x83\x88\x2b\x83\x48\x69\x10\xb1\x3f\x85\x41\x40\x49\x07\x51\x36\x4e\x27\x5e\xb6\x07\xd4\x15\x75\x9c\xf4\xee\xdd\x0c\x66\x7d\xbd\x56\x9b\x0c\x3c\x17\xab\x17\xf2\x73\x6b\xcb\x70\x1a\x15\x97\xb0\xa2\x3f\xe1\x6d\xaa\x38\x3e\x30\xb7\xc2\x48\x65\xc2\x4d\x4c\xa3\x20\x06\xd3\x2b\xb6\xce\xf9\xcf\x0c\xb5\x84\xb6\xe7\x84\xfe\x65\x9b\x41\x6f\xb5\x19\x24\xcf\xc5\xee\x01\xb7\x97\xb0\x04\xf4\x5b\xc2\x12\xe0\xc5\x39\xbc\x2b\x60\x28\xb9\x50\xf1\x33\xfc\x85\x80\x81\x9e\x92\x1b\x76\x53\x4a\x4f\xa4\xfa\x87\xf4\xd3\xb0\x9b\x72\x23\xa0\x8d\x69\xbb\xe9\x37\xb4\x9b\x7e\x83\x35\x8b\xab\xb0\x07\xab\xd0\x5c\x15\x0b\x29\x26\xaf\x28\x85\x51\xc8\xf3\x8d\x61\x76\x04\x21\xc0\x7b\x43\x3d\x37\x5b\x96\x28\x14\x1b\x1d\x53\x5b\x5c\x80\xf4\x50\xbf\x38\xe6\x8a\x68\xd2\xe9\xbb\x62\x55\xa2\x38\x1d\x24\x1d\x3d\x2f\x6a\x53\x9d\x06\xcb\x1d\xfa\x84\x7e\x69\xab\xc9\x79\x19\xe2\x8c\x19\x53\xe8\x8e\xa2\xe0\x04\xb7\xaf\x6d\xe3\x0d\x67\x26\x07\x8e\x8c\xdf\x52\xeb\x9b\x9a\x4f\x5e\xc4\x13\x56\xdd\xa8\x62\x6a\x71\xf4\x53\x55\x81\xfe\xeb\x6d\xad\x19\x41\x26\x08\xcd\x24\x33\xd5\x27\x19\x62\x86\x6c\x3b\x61\xa6\x15\xa6\x4e\x73\x82\xf2\x9a\x71\x23\x04\x96\x5d\x7e\x57\x2c\x3c\xa5\x9c\xcc\x9d\x5d\xa0\x77\xc5\xa7\x53\x9b\x2b\x53\x2a\x52\x60\xba\x52\x11\xd7\x2b\x17\xc4\x93\xb7\x44\x8c\xc4\xd8\x27\xad\x14\xea\x56\x22\x77\x89\x0b\x0d\xad\xbb\x69\x70\xc9\xb9\x9a\x37\x55\x35\x83\xa5\x37\x55\x1a\xea\xca\x6c\x13\x41\xe0\x36\x21\xac\x24\x5d\x55\xc3\x07\x63\x40\x3e\x64\x8d\x62\xaf\x3f\x92\x2f\x48\xd0\xf9\x46\x4f\x18\x3e\x60\x44\x83\x31\xfb\x4c\x21\x74\xcd\x65\x65\x21\xd9\x31\x74\x2e\x64\x09\x9a\xae\xbc\x51\x9d\x75\xca\x4a\xc0\x71\xc4\xd4\xbe\x2d\xab\x91\x92\x26\x70\xce\x0b\xb0\xd0\x5d\x30\xdb\xe4\xf4\x81\x09\x68\xde\x07\x2d\x49\x94\x22\xd2\xa9\xc0\x00\x98\x5e\x86\xb9\xe4\x50\x69\xe6\xc3\x61\x62\x2e\x91\x35\x05\x53\x9d\xdd\xca\xe0\xb5\xc7\x96\x62\x40\x8b\x40\xeb\xca\x64\x12\x7a\xdb\x38\x58\xda\xc1\x20\x14\xbd\xed\x30\x0a\x7d\x5c\x85\x61\x27\xf1\xd3\x0e\xa5\x73\xcb\xf9\x24\xac\x50\xb1\xb4\xf6\xda\xf3\x61\xb0\xd2\x83\xa6\xdc\x52\x8e\x36\x3f\xa7\x6a\x5c\x74\x71\x38\x1f\xec\x12\xcd\xac\x61\xde\x59\x0e\xdc\x38\x10\x58\x07\xe3\x2e\xb6\x26\x77\x34\x16\x6b\x24\x9e\xe0\x04\x80\xfa\x34\xed\xc0\xe0\xbd\x65\x27\x00\x74\x4e\xe9\xea\xee\xbc\x03\x14\x95\xe2\x7f\x2b\xfc\x2f\x84\xff\x74\xd7\x73\xc1\x97\x4f\xf1\xef\xca\x1d\x9c\x0e\xa9\x22\x4c\xc0\xf6\x6e\xed\xfe\x68\x39\xcc\x14\x53\x39\x0f\xe6\xc3\xd3\x11\x51\xc0\x0a\xd5\xb5\xd3\xe1\x7c\x24\x9a\xa2\x4a\xfe\x0c\x71\x32\x6b\xb7\xe1\x43\xbb\x1d\x0e\xf3\x76\x7b\x66\xb5\x8f\xc9\xc2\x2e\x71\xf5\x44\x1a\xd2\x45\x10\x7b\x27\xc1\x74\x70\x32\x84\xfe\x4e\x70\x8a\xe5\x7d\x4b\x73\x98\xf9\x13\x98\xf9\xc1\x22\x58\x08\x62\xb8\x9c\x60\x7d\xfd\x84\x3b\x88\xf2\x09\x8b\x4f\x13\xa4\x94\x60\x86\x52\x2f\x1c\x62\x1c\xc8\x79\x70\x0e\x2b\x5d\x26\x82\xc2\xdb\x44\x30\xc1\x95\xb7\xc2\x0b\xc0\x87\xc1\xa9\x9b\xef\x05\xa7\x30\x1a\xf8\x6f\x8a\x08\x8e\x79\xaa\x30\xab\x16\xbf\x29\x89\xaa\xe5\xfa\xa8\x58\x3e\x4c\xcb\x12\xf0\xc1\x09\x1a\x67\x35\x1e\xc8\xcb\x96\x72\x04\x05\x21\x87\x72\x47\x20\x96\x4f\xc5\xb3\xcb\x33\xea\xe2\xb5\x4a\x30\x93\x0e\xce\x88\xfb\xdd\x11\x20\x7b\x8f\xf7\x2d\x66\x63\x7c\x34\x59\xa3\xbd\x3f\x4c\xb9\x0a\x50\x85\x63\xea\xe5\x7b\x4b\x18\x00\x94\x01\x00\xac\x32\x72\x84\x53\xef\x94\x8a\x10\xa1\xec\x21\x8d\xec\x61\xc8\xe0\x16\xaf\xd8\x6a\x2f\xf7\xd4\x1a\x09\x72\x93\xfd\x06\x2b\xc5\x80\x83\xa9\x72\x9e\xc5\x8a\xb5\x9f\xdf\x8c\xb5\xcb\x3b\xcd\xce\xcd\x3c\x32\x1b\x3d\x04\xb4\x31\x9e\x6a\x8b\x32\x95\x5e\x82\x30\x48\x50\x51\xc9\x41\x77\x06\xce\xcb\xf5\x82\x61\x44\x3b\xd0\xb9\xf0\xc3\x2f\xe0\x0b\xc8\xea\x3c\xc8\x6f\xe8\x3a\xc8\xb5\xeb\x60\xa8\x73\x2c\x05\x5a\x5f\x8e\xa0\x6c\x83\x57\xe1\x93\x69\xd0\x81\x8a\x5e\x80\x56\x57\xec\xf5\x89\x12\x61\x72\x0d\xd7\xf4\x05\xbb\x6e\xfb\xe1\x15\x72\xdb\xfb\x8c\x6f\x3f\xe0\xc3\xff\xd6\xf6\xc3\x7d\x13\x34\xda\x8b\x68\xb7\x8f\xad\xad\xac\x97\x35\x6b\xd0\xd6\xd3\x2e\xcc\x9c\x5c\x55\xc7\xf5\x88\x23\xd4\xef\xa1\x7b\x1a\xf7\x1d\xc8\x95\x8d\x69\x0c\xb7\xba\xb2\x8d\xdd\x70\x43\x07\x7b\x87\x3a\xd8\xbb\x24\x00\x88\xd0\xcc\xf6\x50\x3f\x33\xd5\xb0\xa7\xb6\x8d\xe8\x89\xd0\x06\xe8\x96\xb3\x7d\xec\x16\x59\x3e\x0f\x13\x76\x15\xdf\xc7\x10\x67\x9e\x7b\x95\x1c\xcd\xb4\x1b\xa5\x39\xfb\x20\xe4\x54\x16\xa0\x52\x2e\x7f\x1f\x7c\xc7\x23\x9b\x46\x40\x78\x61\xdd\xc3\x63\x48\x5c\x1d\xe0\xc4\x9d\x78\xe8\xea\xc9\x82\xc8\x8a\xa6\xda\xb8\x0d\x8a\xbb\xef\xae\x38\x97\x22\x8f\xc2\x9b\xfa\x18\x10\x6a\x66\x20\xd1\x44\xa8\x51\x0a\x0c\x43\x27\x83\x61\x0b\x47\x05\x6d\x56\x93\x9f\x44\xc4\xac\x8c\x44\xcc\x8d\x1f\x12\x91\xe4\x42\xf9\x70\x75\x7a\xee\x95\xd0\x6c\xb1\x0e\x22\x2f\xc7\x5b\xe2\x34\x86\xa0\x71\x0f\xf1\xc0\x6b\x53\x8e\x27\x51\x17\xbb\xc5\xb7\x74\x03\x26\xd1\xa9\x2c\xc7\x9f\x45\xe1\xc1\x16\xde\x24\xf7\x24\x39\xfd\x64\x9e\x98\xc8\x26\x9d\xd2\xf5\x5f\xf2\x08\x5c\x23\x4a\xe0\xda\xa5\xf7\x02\x97\xde\x6b\xb1\xf4\xf0\xa1\xbb\x4a\xf2\xd3\x68\x5e\xdc\xab\xe4\x77\x7a\xdd\x64\xfb\x7e\x63\xd9\xbe\x8f\xaf\x59\x2b\xbf\x34\x6f\xed\x9c\xb2\x70\xf6\x75\x5b\x3b\x2f\x8c\xe5\xf1\x27\x2e\x8f\x3f\x93\x00\x80\xb0\xb6\x76\x1e\x5c\x8b\x82\x27\x88\x82\x33\x81\x82\x27\x37\xe1\x3e\xe7\x37\xe0\x3e\x06\xef\x09\x67\x33\xa7\xca\x79\xce\x9a\xd0\xf9\xab\x85\xce\x67\xb6\xf2\xda\x44\x1d\xcc\xa2\x0e\x46\xc1\x3e\xa4\xdd\xe2\x33\xba\x51\xd1\x7f\xc0\x97\x2a\x56\x67\x8b\x65\x71\x49\x89\xa4\x8e\xa0\xc0\x19\xb3\x62\x05\xee\x31\x33\xde\xcb\x9e\xb9\xbf\x92\x5a\xec\x97\xe6\x6d\x89\xe4\x6d\x89\x31\x83\xcc\x8c\x6d\x7a\x62\xcc\x53\x81\xc9\xb0\x8b\x2c\xb8\xc7\xd9\x98\x39\x55\x1f\xae\x9d\xaa\x9f\x71\xaa\xde\x88\xa9\xfa\xf9\x7f\x69\xaa\xde\x98\x60\xd1\xbc\x55\x85\xc4\xc3\x2d\xa8\x63\xd9\xdf\x42\xdd\xcf\x06\xea\x12\x44\x5d\x92\x05\xd0\xdd\xab\x0a\xf3\x7f\x64\x42\xe0\x19\x27\xd8\x52\xe2\x5d\xa9\x79\xa9\x83\xf2\x13\xd2\x2e\xe7\x2e\x05\x33\xd8\xdf\xcd\x0d\xb2\x0c\x37\x24\xb0\x1c\x88\x86\x04\xa3\xe1\xb9\x22\x52\x49\xed\xf5\x07\x2a\x67\x78\x5a\x93\x0f\x51\x86\x45\xe2\xda\xc5\x2b\xb2\xf8\xf2\xa6\x54\x5f\x21\xfe\x12\x99\xec\xdf\x52\xe6\xa4\xa0\x58\xcb\x2c\xf6\x4b\x3c\x1c\x95\x92\x4f\x3d\xdb\x98\x05\x33\xcb\x0c\x36\x62\xee\x01\x66\x66\xa8\xcc\xe7\x8a\xcb\xd4\x6e\x43\x3c\x01\x37\x7f\x21\x7b\x79\x4e\xe1\x13\x46\xe8\x2c\x5f\x52\x99\xc5\x96\x8c\x0e\x3e\xda\xc9\x35\x69\x9c\x95\x5d\xc9\x2e\x7f\xd7\x7a\xc9\xa6\x69\x36\x6b\x19\xbb\xf5\xd2\x4b\x98\x5d\x5e\x31\x45\x91\x6f\x19\x25\x5a\x75\x14\x43\x77\xd7\x53\x71\xaf\xe2\x95\x61\xf3\xbd\x15\x95\x37\x65\x82\x60\x74\x71\xd6\xa6\x7b\xb0\xb8\xf4\x5f\x7b\xb9\x59\x44\x9c\xe9\xe7\xa1\x5d\xd2\xdb\x21\x8f\xf6\x63\xba\x03\xf4\xe0\x03\xba\xe5\x69\xb2\x9d\x8c\x46\xd4\x95\xb9\xac\xb9\x90\xa3\x5b\x03\x8d\xd0\x00\x6d\x2f\x53\x96\x21\x3b\xaf\xd0\x82\xee\x52\x34\xb2\x4e\x70\xd5\x53\xa7\xe2\x10\x2f\xf8\x07\xf5\xc2\xaa\xc2\x45\x84\x55\x49\xbe\x92\x1f\x8d\x97\x65\x89\x51\x45\xf0\xe2\x84\xba\xbe\xe4\x0f\x97\xf4\x70\xcc\x1f\x8e\x1d\x66\x5f\x4a\x62\x66\x1e\xd5\xcc\x54\x8f\x84\xaf\x78\x4a\x68\x89\xc5\xb1\x19\xed\xa3\x17\x41\x1e\x3a\xe4\x92\x75\x31\x10\xe3\xb2\xa2\x2a\x89\x38\x75\xb1\xd1\x23\x22\x8e\x25\x81\xb7\xdb\xdf\x38\x11\x0f\xfc\xc7\x63\xbe\x65\x89\x8f\x18\x86\x81\xb1\x61\x78\x7b\xaa\xa8\x45\xf1\x66\xbc\x25\x0e\x79\x25\x71\xaa\x6b\xbe\x12\xa3\x68\x4c\x4a\x63\xc4\x3a\x21\x16\xad\xa0\x29\x91\x30\x43\x72\x01\xd0\x2f\x07\xa8\xc9\xb2\x20\x15\x11\xdd\xbb\xb8\xd1\x61\x9c\xff\x6f\x0c\xd0\x74\x92\x91\x3c\x8e\xee\x47\xa3\x6f\x90\x70\xf4\xc1\x55\xd7\xff\xc6\x31\x1e\x71\x9c\xea\x30\x08\x46\xf1\x79\xbb\x7d\x57\xc7\x68\x86\x92\x3e\xd0\xf7\x6d\xc4\x98\xa8\xb5\xdf\xc8\xe0\x7e\x67\x16\x87\x53\xa5\x29\xf7\x74\x41\x27\xc6\x12\x4d\xfd\x05\x5b\xee\x84\x3b\x2f\xc3\xe4\x84\xed\x1c\x5f\xee\xf4\x5a\xb4\x17\x85\xf7\xd7\x56\x32\xf0\xf4\xf7\x7b\x20\x5f\x4c\x6f\x4a\x9f\xa7\x5d\x0d\x8f\xf1\xb2\x1b\xaf\x18\x62\xb9\x24\xd8\x4b\x5c\x1d\x87\x93\xe9\x4c\x88\x2c\x99\xa9\x88\x1d\xec\x55\x86\xeb\xd0\xf8\x8c\xe4\xae\xf4\x73\xca\xa2\xd8\x71\xd8\x5e\xe1\xee\x27\x7b\x7d\xb7\xd3\xe7\x5b\xa8\xaa\x02\x77\xe1\x2b\x56\x1f\x65\x83\x88\xc7\x6e\x1a\x8c\xe4\x9d\x5e\xa0\x75\x24\xbd\xb3\x91\x24\xca\xea\x4b\x5b\x78\xea\x52\x33\x2d\x86\x91\x6f\x16\x50\xe1\x9b\xe9\x68\x9b\x80\x4b\xb5\x1c\xca\x06\x69\x0d\xb8\x6f\x2c\x99\xaa\x77\x70\x71\x2b\x47\x49\x86\x31\x26\x57\x81\xff\xd6\x92\x20\x4c\xb1\xc4\x74\xb4\x32\x60\x5c\x73\xfc\xe7\x17\x89\xe4\x96\xaf\x2e\x17\xc7\x29\xa6\x25\xdb\xf6\xb5\xd2\x90\xe1\x82\xfd\xa5\xe2\x5e\x34\xa2\x57\xac\x2f\xa0\xe6\x17\x46\x7e\xc9\x5f\x1b\x37\xe4\x95\x36\x58\x6c\xc8\x65\x63\x44\x7f\x6c\x6d\x60\xef\xfa\x06\x0a\xf3\xd6\x33\x95\xbf\x4a\xa5\x8d\xfc\xf5\xd5\xf3\x67\x5d\xfe\x3a\x9a\x23\x9f\x34\xfd\xce\xcc\x90\x28\x91\x63\x34\xaf\x77\xb1\x6c\x1b\x10\x03\x21\xfb\x3e\x06\x45\xda\xe1\x90\x99\xbc\x91\x4b\x2d\x61\x5c\x41\x72\xe7\x4b\xa4\xf4\x42\x8e\xea\xa9\x03\x48\x18\x57\x09\xc6\xb4\x95\xfc\x39\x19\xb1\x4a\x2c\x7a\x86\x09\xab\xb2\x4e\x08\x5c\x87\xd2\x3b\x91\xc4\x73\xcb\x5e\x35\x2c\x1d\x34\x86\xa6\x42\x66\x73\xaa\x31\x2a\x64\x37\xc1\x1b\x90\x1f\xf4\x8e\x32\x1e\xb8\x30\x3d\x25\x15\x93\x18\xd4\x19\x64\x87\xb7\x6e\xdf\x3a\xf8\xa9\xff\xe3\xad\x3b\xb7\x30\x25\x1f\xbe\xba\x7b\xb7\x7f\xa7\x44\x9f\xef\x5e\xff\x8e\x77\xfb\xfb\xfe\x8f\xb7\xef\xfc\xd4\xfb\xc1\xf8\x7a\x4b\x7c\xbd\xe5\xdd\xc1\xb7\x0e\xeb\xdc\xfa\xf1\xfb\xdb\x07\x3f\x1d\xf4\x7f\xfa\xbe\xec\xb9\xff\x2e\x44\xd1\x7f\x63\xb1\xfe\xf7\xde\xc1\xc1\xed\xef\x7f\x3c\x38\xb8\xa3\x1b\xe1\x5f\x6e\x79\xb7\x0e\xbe\xff\xfe\xf6\x8f\x3f\xfd\xd4\xfb\x09\xbf\x60\x02\x2f\x51\xc7\xdc\xb1\xaf\x5c\x52\xfc\x6f\xd6\x39\xf8\xfe\xce\xed\xdb\xb7\xee\xfc\xf0\xfd\x4f\x1d\xa7\xb8\x7b\xf7\x7b\xb1\x4d\x8f\xc3\xa7\xdd\x87\x44\xa4\x39\x35\xee\x62\x43\x57\xba\xb7\x4a\x82\x16\xbf\x6b\xa2\xe5\x4d\x93\xe0\x8e\x17\x27\xe4\x93\x4d\xbc\x65\x12\xc4\xc0\xbf\x80\xd5\x63\xc2\xfb\xd3\x44\xe6\x41\xc6\x74\x1f\x33\xf3\x69\x50\x38\xa7\xde\x1c\x56\x9f\x33\xe3\x7f\xce\xf1\xcf\x1c\x6f\xa4\x96\x29\x61\x17\xf4\x48\x7e\x85\xe0\x84\x7f\xe2\xc9\x72\x83\x4b\x7a\xba\x97\xe7\xe9\x34\xa2\xab\x01\x83\x23\x7a\xf3\x3c\x9b\x91\x55\x79\x0c\x4f\xbc\x1e\xf4\xd1\x95\xb5\xa0\xa3\xee\x2b\x56\x04\xe7\x44\x8a\xe7\x30\x86\x7f\xfd\xeb\xe8\xe8\xf1\xd3\xa7\x6f\x5e\xdf\xfb\xf9\xc9\xe1\xd1\xe3\xd7\x87\x2f\xe9\xc7\xd1\xbf\xfe\xd5\xf2\x16\xb5\xef\xbf\x1d\xbe\x3b\x7c\xc0\x3f\x9e\xd4\x2b\x3f\x7b\x70\xf8\xa7\xfc\x7c\x59\xfb\xfc\xfc\xe5\x83\xc3\x97\xf2\xf3\x11\xa6\x72\x3b\x06\x94\x79\x87\x49\x70\xe0\x7d\x82\xd2\x75\xc9\xcd\x99\x55\xbb\xcd\xff\x76\x65\x3c\xbd\x77\x41\x6d\xcb\xc7\x96\x77\x3f\x09\x3e\x81\x1a\x71\x91\x0c\x0e\x8d\x79\x2a\xd2\x57\xb4\xdc\xeb\x99\x41\x5a\xe3\xc7\xa2\xee\xa4\xb5\xf6\x0e\xbb\x30\xaa\x57\xc1\x51\x02\xbf\xde\xde\x7b\xf2\xe6\xf0\x55\x70\x8c\xbf\x0f\x9f\xbd\x7e\xf9\x18\x1e\x0e\xf1\x41\x37\x1b\xd1\xb5\x70\x45\x50\xe9\x2a\x5d\x65\xd3\x8d\x39\xbf\x24\x28\x98\x8b\xc4\xa8\x37\xbe\x0f\xbc\xbe\xb9\xca\x1a\xc8\xe1\x35\x92\xc3\xeb\x6e\x3a\x6f\x28\xf3\xda\xe4\x52\xde\x6b\x1b\x16\xf6\x71\x63\xab\xaf\x6f\x84\x20\x11\x7a\x7e\xa4\xe0\x6e\x41\x9b\x3b\x57\x2d\xaf\xb5\x6e\x55\xba\x33\xf3\x99\x34\xf0\x7d\x6a\x87\xca\xc8\xeb\x53\xaa\x67\xa9\xd4\xd5\x5d\xf4\x18\xe8\x50\x60\xee\x48\x53\xc1\x10\xb5\xe8\x76\x2a\xaf\xee\xce\xaa\x0f\x6f\xd3\xc9\x0f\x31\xc4\x8f\x5c\x96\xa0\x9a\x84\x67\xc4\x1a\xab\xa6\xd5\x2b\xa4\x44\xdd\x3f\x2a\x75\x0b\xe7\xb1\xf7\xda\xf5\x1e\x5b\xc8\x95\xde\xc0\x2d\x33\xfc\x02\x6b\xbd\x68\x9e\xe1\x17\xd6\x0c\xbf\xb0\x9a\xd6\x19\xb3\x37\x36\xfe\xe2\x6f\x4c\xf4\x18\x26\x7a\xd2\xaa\xf4\xfa\x05\xe8\xec\x6f\xa8\x7a\x13\x74\xf6\x09\x9d\x0f\x10\x31\x0f\x9a\x11\xf3\xc0\x42\xcc\x83\x0a\xe9\x17\xdb\xa9\x3f\xca\xf1\xfb\x07\xf8\xc5\x99\x23\xcc\x1b\x31\x44\xe8\x50\x31\xc9\x17\xc4\x1c\x5f\xd6\x18\xd8\xab\xc3\xdf\x89\x79\x0d\x0c\x52\xc1\x24\xda\xb4\x27\xe2\x9c\x79\x2f\x5c\xef\xcc\x80\xc6\xca\x75\x61\x89\x1d\xc4\x39\x1a\x0b\x85\xbc\x9a\x8f\xef\x13\x89\x0c\x18\x85\x3b\xf1\xd9\xda\x6a\xea\xda\x43\x4c\x81\xd1\x0e\x05\x20\xa9\xb4\xc3\x11\xc5\x44\x05\xfc\x8e\x0a\x54\x4c\x1c\x50\xdd\x46\xd9\x5e\xe4\x47\x13\x2f\xe2\x07\x43\xac\x74\xc8\x91\x0e\x5b\x89\x9a\xa1\xa8\x4d\xe3\x4d\x40\xd0\x6a\x77\xc3\xc9\xc3\x9d\x68\x98\xa9\x43\x45\x91\x27\x20\xec\x74\x30\x28\x87\xf2\x1c\x03\x7e\x9f\x79\x8f\x5d\xef\xd9\x4d\xf0\x6b\x5e\x5e\x51\xc7\x35\x4f\x64\x38\x2e\x08\xc9\x66\x7b\x56\x22\xa3\xa2\xb2\x42\x44\xfa\x43\x28\x63\x28\xd3\xe8\x30\xb3\x9a\xb8\xe9\x3c\xf1\xd6\xd4\xc9\x33\x54\xed\xc9\x3d\xa4\x50\x96\x52\x68\x5d\x90\x9a\xfb\x64\x19\x60\x25\xda\x4b\xfd\x94\xce\x7e\xe3\x3c\x86\x13\xcc\x4a\x53\x9b\xc1\x54\x27\xb4\x4e\x9b\xe1\xdb\x3a\x83\x37\x02\x6e\xd3\x7c\xd6\x40\x55\x30\x75\x86\x91\x9a\xe2\xd0\x43\xe0\x69\x62\x0d\xf0\xf0\x52\x0a\xbe\x96\xee\xe1\x5a\xba\xd7\x84\xd8\x37\x0d\x67\xe9\x44\xfc\xc2\x8d\xf2\x3a\x90\xc1\x67\x8e\x56\x9e\x40\x82\xf1\xbe\x92\x57\xba\x40\x6b\x2f\x9d\xcc\x55\x37\x34\xa5\x83\x5d\x27\x6d\x38\x07\x98\x5e\x7f\x0e\xb0\x69\x10\xcd\x27\x02\x6f\x3e\x8a\x34\xbb\x76\x18\xe4\x8e\xa2\x31\x58\x13\x75\xa1\x12\xc1\x6c\x9d\x40\xa6\x73\x04\x2a\x2f\x0f\x8e\x79\xc4\xf8\x02\xa5\x53\x7f\xfc\xf0\x07\x5f\x9b\x4f\x70\xbe\x9e\xfc\x8f\xcd\x57\x75\xf9\x28\x45\x30\xab\xbc\xa0\x7b\x0f\x44\xf0\xb2\x24\xd8\x01\xe7\x7a\x78\x3d\x8f\x9e\x28\x9b\xe3\x0d\xec\x89\x4e\xac\x89\x1e\x48\xa2\x4e\x8d\x83\xf3\x78\xd7\x0f\x2c\x3d\x27\xac\x36\xc9\xaf\x40\xd4\xf3\xdf\x84\x94\xff\xb1\xf9\xdf\x8e\x92\x4d\x33\x8e\x4e\x95\x61\x25\xc7\x04\x53\x48\xe0\x49\xc2\xcc\x34\x1f\x6c\x40\xc3\x17\x14\x20\xc7\xca\x39\x37\x7c\x11\x1c\x9b\xa0\x7b\x95\x80\x8d\xf3\x96\x1b\x37\xbf\x79\x6f\xf1\xcf\xef\xfc\xcf\x3b\xfc\xf3\x56\x08\x61\xf8\xa4\x84\x2f\x7c\x27\x81\xfc\x8e\x1a\x78\x9a\x78\xcf\x1b\x4d\x03\xf2\xc4\x44\x8b\x15\x58\x07\x7b\x07\x80\x7a\xf5\xec\x18\xe9\xad\x0f\xdc\x91\x7a\x5f\xb1\x93\x0b\x4c\x9c\x0d\x76\x62\xaf\x64\x02\x8f\xdf\xdf\xb9\x73\xeb\x4e\x1b\xf9\x1e\xff\xa5\xfc\x95\x09\x98\xca\x8e\x53\x70\x5b\x12\x7e\x27\xdf\x39\xc2\xb0\x04\xfb\xf5\x7b\xf8\xd5\x43\x63\xd1\x7b\xad\x76\x49\xa2\xfc\x50\x25\x41\xf6\x1e\xdb\x97\xad\x65\x97\x95\xd3\xa1\x15\x57\x37\x58\x8c\x2d\x30\x8f\x30\xc3\xf5\x6e\x4f\xb8\xca\xf5\xa6\x5a\x7f\xbd\x76\x30\x4d\x73\x13\x46\xfe\x00\xc2\x7b\x1a\x2e\x07\x94\x9c\xfa\x29\xbf\xbc\x43\xbc\xe3\xa4\x82\x39\x9e\xbd\x33\xa8\x0b\x74\x24\x9d\xde\xe8\x43\x3e\x3a\x6a\x0d\xb6\x18\x5f\x0e\x54\xe1\xbf\xe1\x97\xcb\x9b\x7a\x06\x86\xdb\xf7\xde\x3d\xb0\xdc\xee\xdc\xf1\x74\x56\x6e\x98\xec\x55\x81\x62\x7a\x55\xdc\x58\x0f\xe2\x87\x54\x4f\x44\xce\xe9\xb5\x5d\x75\xab\x48\xa6\x8a\x5c\xb4\x57\xaa\x11\x61\x6e\xd6\x03\x45\x55\x59\xca\xa9\x56\xdf\x90\xac\xb6\xe0\x19\x1e\x58\x30\xe3\xdb\x0a\xa8\xfa\x0f\xac\x66\x45\x7e\x5f\x3c\xe1\xbf\x15\x06\x01\x80\x3c\xf5\xaf\x73\xd9\x62\x22\x73\x1b\x16\xdc\xb0\xd9\x24\xaa\x81\x54\x4f\x0b\xa5\x3a\x6f\x84\x25\xdb\x06\x4b\x52\x81\x05\xe3\x16\x68\x22\x5c\x2f\xab\x80\xb2\x49\xb9\x31\x4f\xd1\x0f\xea\x68\x36\x78\xb9\x09\x98\x76\x48\x59\x61\xea\xe2\x0c\xce\xda\x77\x92\x80\x8d\x5e\xf0\xe1\xb9\xbe\x91\x14\x30\x32\x0a\x47\x1e\x86\x3d\x27\x3e\xe6\x82\xcf\x08\x7d\xd5\xb9\xdc\xa8\xf1\x28\xa7\xaf\x80\xc7\xdd\x0c\xf9\x26\x7e\x5b\x4f\x19\x90\x59\x30\x6f\x95\xb1\x91\xe6\xb0\x6a\xe3\x8f\x64\x6c\x44\x32\x16\xc7\x95\xf9\x59\x2d\xbb\x86\x39\x38\xad\x2f\x81\xba\x06\x02\x78\x6a\x0e\xbc\x9e\x94\xb4\x71\xfd\xa8\xec\xa4\xb8\x88\xa6\x37\x9e\x6e\x49\x7f\xbd\xad\x13\x6e\x6e\x5d\x1b\x13\x8c\xa3\xa2\x7c\xc0\x9b\xba\xdc\xaa\x9e\x6e\xc2\xfc\x75\x2a\x4d\x15\xdd\x96\x4a\x93\x69\x95\xc6\x93\x4a\x4d\x5c\x78\x0f\x5c\x2f\xfe\x32\x7e\x64\xe1\x33\xfe\x32\x7c\x7e\x0d\x2e\x99\xc2\x64\x63\x67\x5f\x8e\xc9\xbf\x83\x45\x85\xc1\x0a\x26\x97\x24\x14\x96\x26\x80\xd2\xc3\xb3\x9d\x45\x0b\xae\xb4\xb6\xeb\xfe\x83\x98\x24\x8d\xeb\xea\x31\xfa\xc9\x45\x66\x9a\x85\x79\xfb\xb1\x93\x8d\x48\x7e\x39\x7d\xd7\x67\xfc\x0e\x21\xfe\xdc\xc3\xe7\xde\x04\x91\xcf\xb1\xdf\x08\xe0\x3f\x88\x7d\x33\xe1\xeb\x76\xe5\x4c\x1c\x10\x34\x94\x55\x1a\x60\x26\x55\xff\x85\x91\x06\x8c\x94\xb6\x51\x26\x87\x84\xb9\x61\xd4\x33\x66\xbd\xc2\x21\x33\x3c\x36\x52\x5d\xa9\xa6\xd7\x6f\xb5\xe9\x43\xbc\xe9\xc3\x72\xd3\x87\x67\x05\x50\xcb\x87\xc2\xfb\xcd\xf5\x3e\x98\x65\xbe\xc4\x81\x05\xfa\x8e\xf6\x54\x7e\xf8\x02\x45\x04\xc3\x60\x47\xfa\x27\x47\x8a\xca\x5c\x87\x09\x8f\x58\xa5\xc1\x7c\x53\x83\xdf\x18\x62\xb9\x5e\xc7\x54\x09\x6b\x60\xf0\x73\x9c\x8f\xf1\x8b\x79\x92\xd3\xd8\x90\xab\xb6\xc8\x83\x00\x9b\xf8\x92\x06\x63\x9e\x54\x6b\xf1\xbd\x0b\x0b\x94\xcd\x80\xd4\xa0\x98\x27\x35\x30\x78\x79\x6b\x64\x86\x60\xef\x37\xde\x80\x2e\x24\xa5\xdd\x1f\x5e\xd7\xcd\xd9\x5a\x43\xfb\x15\xdc\x61\x0f\x09\xa5\xb7\xc1\x2d\x7b\x11\xe5\x28\x96\x40\xca\x35\x0e\xef\x09\xdf\x0b\x33\x12\xe3\x8b\xb4\x04\x62\x0f\x3e\xab\x74\x44\x71\xff\x0d\x94\x66\x6d\xf7\x12\xa1\xf8\x76\x74\x89\xc8\xcc\x42\x2e\xea\x9e\xa7\x29\x29\xd0\x77\x2a\x57\xc2\x1b\xf9\x2b\x33\xb4\x9a\xf0\x41\xa9\x09\x6c\xa0\xe8\xc4\x72\x93\xfe\x26\x06\x29\x5a\x34\x3d\xa3\xf5\xfa\x78\xda\xd9\x9a\x6f\xce\x4d\xf2\x84\x67\x80\x51\x95\xbd\xbe\xc1\x88\x36\x52\x32\x35\x59\x21\xa0\xeb\x1b\xac\xd2\x16\xc5\xfd\xd6\x69\xb0\x31\x8e\x83\x7a\x1c\x89\xbf\x72\x43\x98\x16\xe6\x98\x29\xf7\xd4\xa4\x46\x99\xea\xb4\xf7\x16\xfc\x65\x4c\x84\x92\xb8\xd7\xe0\x50\x9e\x1a\xff\x4a\x3c\xd2\xc1\xf5\x0d\xb8\xc4\xa6\xff\xf7\xf1\x89\xbd\x8e\x8c\xdf\x37\xc7\x2b\xe6\x5a\x6b\x62\x1f\x17\xcc\x79\x29\x39\x8f\xdb\x54\xe9\xe7\xcb\x66\x06\x68\x54\x64\x0d\x55\xad\xb8\xc8\x06\x34\xf1\xf3\xa9\x0d\x49\xc8\x31\x40\x1a\xaa\x87\xf9\x3d\xbe\xd2\x1c\xcc\x01\x70\x74\x04\x26\xfa\x2a\x63\xcf\x71\xf1\x56\xe2\xc4\x38\x4b\xaa\x74\xaf\x5a\xde\x2c\x85\xd4\x01\x2c\x83\x39\x98\xbd\xf0\x84\x16\xb5\x76\xf5\xed\xda\x1b\x5b\x36\x5b\xa9\xe1\x45\x0d\x6c\x73\x7d\xc1\x63\x2a\x35\xaf\xdb\x98\x21\x1f\xc2\x66\x59\xf6\x35\x26\x02\x4f\xcf\x63\x88\xd9\x2d\x0a\x2e\x6a\xe5\x30\x79\xa4\x85\x08\x6d\x8b\x74\xfd\x1a\x18\x06\x76\x1a\xe5\x99\xe4\xdc\xd5\x19\xc2\x64\x30\x8a\x67\x1b\x1c\xdb\x2b\x4c\x76\xed\xfa\x15\xf2\x50\xe1\x4d\x66\x0c\x37\xb1\x6e\x82\x2c\xca\x41\x07\x09\xde\xf0\xe3\x87\x6f\x6a\xdb\x48\x4f\xef\xbd\xe0\x7b\xe0\x0f\x93\xc0\x1c\xc7\xe0\x61\x82\x69\xa2\x50\x0c\xc0\xaf\x15\xfc\x7a\x98\x08\xe1\xee\xa9\x5f\xc0\x1f\xe0\xb7\x14\xde\xde\xc3\x6d\xfa\x4d\x35\x7f\x89\xda\x5a\xc5\x7b\x4e\xf9\x79\xf9\x48\x25\x4d\x19\xf2\xbd\x06\xd0\x17\xbf\xc1\x3c\x9a\xe3\x74\x82\xf9\x1c\x94\x8b\x14\x9f\xfb\xc6\xc5\xe6\x76\xcf\x4d\xb2\x3f\xd3\x89\x74\xf4\x09\x3a\x9e\x31\x07\xcf\xcf\x99\xb0\x2c\x01\x96\x79\x10\x4b\x58\xe6\xc3\x65\xbb\xbd\xfb\x8d\x93\x7a\xf1\x78\x49\x60\x0c\x96\x00\x1a\xa1\x13\xf8\xee\x70\x89\x5a\xed\xe9\x88\x3e\xf6\xf1\xb8\x65\xe8\x4f\x4d\xf3\x9d\x4e\x7e\x60\x42\x1e\x67\x5a\x96\xbb\xa7\x94\x53\x13\x13\x16\x4d\x79\xaa\x8d\x58\x79\x3a\xd1\x49\x7e\x0a\x5d\x4d\xf1\xe4\x9c\xb8\xe4\x2e\x78\xa4\x0e\xf6\x52\x42\x1a\x9e\x6e\x58\x1e\x9d\x03\xca\x95\xb4\x24\x43\x4a\xcf\x83\xd9\x28\xf6\x23\x27\xd6\x09\xf0\x47\xd3\x11\x9e\x1d\x9d\xef\xf5\x47\xe7\xe2\x20\xc6\x39\x00\x1b\x58\x0f\x94\x1d\xc8\x3f\xe7\x27\x96\x78\xaa\x20\x6f\x26\x54\x08\x99\x4a\xeb\x5c\x28\x04\x32\x35\x12\x1e\xb6\x5a\x7b\x3f\x5f\x3f\xe9\x95\x30\x3e\x4a\x97\x23\x0d\x80\xfe\xdd\xbb\x8e\x23\xaf\xf1\x46\x4f\x66\x81\x19\x7e\x30\x83\x02\xf5\xcd\xd3\x89\x0d\x0c\xa5\xc7\x49\xdb\x91\x3b\xca\x38\x43\xa3\x1c\x61\xe3\x90\xe1\xcb\xbd\xbe\x3b\xe1\xae\x3b\xcc\x06\x24\x3c\x37\x36\x78\x8d\x5a\xa1\x71\xc0\x57\x05\x16\x52\x18\x21\x86\x48\xba\x32\x57\xb5\xc3\xe3\xee\x12\x1f\x93\xd7\x30\x91\x85\x88\xb2\x06\x4d\x4d\x48\x81\x98\x30\xba\xd1\x99\xb6\x57\x7c\xdb\x23\x6e\xb7\x23\x3b\xc1\x14\xd2\x04\xb6\xb9\x0c\x00\x6e\x28\x07\x70\x03\xbd\xe9\xe1\x78\xa7\x41\x3c\x9a\xc3\xa4\xa8\x4b\xc8\x31\x0d\xd6\x29\xb2\x3c\x1c\x98\x86\x97\x0e\x44\x42\xdb\xa7\x55\x72\xc3\x4e\x67\xed\xf6\x5c\x51\xd1\x67\xd5\x3b\xa5\xec\x99\xe3\x29\x3f\x6f\x46\x0d\x40\xd1\x5d\x28\x8b\x5e\x6b\x59\xbe\xdd\xfe\xb3\x70\xe6\xe3\xfe\xbf\x97\x7a\xc9\xf1\x47\x51\x01\xca\xf7\xab\xe5\x67\xaa\xe8\x8c\x47\xf3\x34\x92\xe7\x02\x86\x36\x1b\x4d\xfd\xe9\xbf\x57\xfe\xb4\x5c\x79\x27\xf4\x9c\x03\xbf\xf5\x96\xde\x0c\x08\xca\x9f\xf2\xdf\xf0\x6b\xa5\xdf\xca\xf9\x3f\x17\x14\x29\x92\xcc\x2d\xcc\x44\x71\x27\x06\x75\x52\xae\xa2\x85\x77\x02\xf3\xff\xe8\xef\x91\x67\x9d\x34\x25\x65\x72\xd2\x8b\xf4\x9e\xe2\x28\xad\x52\x1f\x2a\xf3\x8f\xfe\x27\xe9\x8f\x53\x96\xa4\x40\x4e\x3d\x71\x30\xc5\xe4\x4e\x78\xaa\x0a\xa6\x36\x6e\x20\x3b\xa0\xa6\xb8\x99\x9a\x96\x66\x32\x07\x55\x43\x10\x27\x25\xe7\x23\x0a\xe0\xbc\x0a\x8f\x7f\xce\xf7\xf6\xbc\x8f\xc9\x70\xae\x4f\x67\x23\x7d\x4d\x81\xc2\x72\x71\x42\x6b\xde\xe9\x08\x56\xd9\x44\x0f\xb3\x20\xc7\x0c\x38\xc0\x74\xbd\x53\x83\x63\x39\xba\xc3\x60\x6e\x4e\xf2\xcc\x98\x64\xca\x0a\x35\x07\x32\x5e\x7b\x9f\xff\xcf\x04\xcf\xe7\x2f\x10\x3c\x6a\x7a\x31\xd1\x56\x86\xd3\x9b\x8a\xe9\x95\xa2\x88\x1c\x24\xbb\x02\x47\x22\x13\x9a\xec\x7b\xca\xb5\x04\x23\xb9\xdb\xaf\x5a\x17\xc2\x04\x6b\x3c\xbf\x9b\xda\x3d\xfc\x3f\x91\x6a\x53\xc1\x49\xcc\x8d\x5e\x4a\x91\x66\x8e\x08\xba\x24\xde\xf2\xff\x01\x31\xf6\xb9\x06\x1b\xc8\x34\xef\xe3\xf5\xe4\x24\x7d\x1a\x4e\x62\xa4\x8b\x44\x34\x8e\x8c\xc7\xfe\x04\x39\xc0\xc7\xeb\x49\x44\x64\xf1\x93\x49\xd1\x53\xb9\xac\xbf\x71\xa2\x4a\xf3\x02\x1d\xce\x74\x94\x4a\x9c\xa9\xbe\x56\xae\x22\x11\x98\x8a\x15\xf7\x28\x60\xde\x07\x1f\x68\xa7\x8e\x64\x03\x2d\x58\x1d\xd3\x69\x28\xbc\xd4\xe7\x6c\x0c\x30\x4e\x5c\x91\x47\xc2\xa4\x3c\x20\xe3\xc8\x15\x9f\xd1\x48\xb2\x54\x31\xa9\x91\x7f\x6e\x7a\xb9\x35\x2a\x45\xd2\x2d\xa8\xec\x98\x5c\xc7\x48\xc7\x34\x0c\xb2\x41\x66\x86\x0f\x45\xb8\x37\x31\xb1\x76\xd1\x31\xba\xf5\xe7\xa6\x3e\x1f\x7d\x31\x20\x9c\xab\x6e\x06\x43\x65\x97\x93\x80\x50\x22\xb1\x76\x3b\x55\xb6\x04\xb6\x5a\x01\xae\x42\x15\x5b\x63\xd9\x0a\x63\x9e\xc8\x81\xfd\x47\xe1\x1d\xba\xde\x1f\x66\x03\xe8\x80\x35\xcd\x2d\x39\x86\x42\x58\x1a\x58\xc8\x93\xa1\x8a\x94\x9c\x74\x20\x43\x09\x70\xb3\x8c\xd1\x28\x61\x80\xb8\x53\x33\x63\x9f\x80\x67\x23\x27\x12\x7d\x5e\x89\x63\x3a\x2a\x1d\x17\x65\x2e\x95\x5f\xd5\x21\xde\x4c\xce\x99\x38\xcc\xab\x9e\x75\xac\x4e\x32\x6c\x6c\x04\xca\x8c\x85\xb9\xc3\x37\x1f\x47\x09\x45\x84\xe9\xb6\x29\xef\x35\x4e\x44\xa5\x2d\x99\x73\x4c\x48\xe3\xa6\x46\xf8\xd5\x24\x74\x1e\x42\x40\x6c\x02\x20\xdf\x0d\x2c\xe4\x04\xbf\x61\x5a\x4e\xb0\x30\xa7\x69\x52\x44\xc9\x8a\xad\xed\xcf\xc6\xef\x2e\xcf\xc0\x6a\xde\x27\x40\x7c\xed\xe7\xc4\x7b\x84\xa1\xd7\xfb\xb7\xbd\xcf\xf4\xf7\x00\x04\x25\x3d\x0f\x40\xfc\x32\xef\x77\xd7\x8b\x59\x73\x48\x21\xb6\x6e\x45\x15\xc6\xc6\x11\xf8\x2f\xf2\x3e\xe3\xad\xe7\x3a\x7e\xd2\x6a\xa6\xee\x7e\xa6\x53\x64\x2a\xea\xcf\xeb\x0d\x31\x05\xe8\xd0\x38\x53\xa2\x9c\xfa\x98\x0c\x8e\xba\x32\xd2\x03\x25\xc1\x91\x74\xce\x69\x37\x13\x48\x05\x91\x75\xa2\xc0\xdc\x19\x15\x10\x36\x3a\xac\x17\x96\x9b\xcf\xaa\xb3\xd9\xbd\x4c\x10\x89\xd8\x3a\xae\xb4\x71\xc8\xf1\xa8\x35\x9e\xc8\x35\xfd\xa5\x20\x43\xe8\x37\x97\x1c\xfc\xf5\x92\x72\xd2\x14\x5e\x5f\xba\x5b\xac\x7e\xff\x11\x37\xac\x89\x34\x15\x36\x2c\xd2\x60\x48\xff\xab\xc8\x84\x91\x98\x1e\x5b\xb1\x86\x31\x1d\xc6\x97\x3a\x6f\xcf\xe9\x52\x5a\x6b\x28\x28\x1b\xeb\xd1\x04\xda\x9b\xc7\xf4\x80\x2c\x67\xc9\x86\x83\xc0\x89\x7b\x75\x8c\x77\xc7\xf6\x3c\xbc\xc1\x5c\x18\xb3\x03\x9d\x71\xa3\x37\xc8\xf4\x6d\xe7\xc8\x30\xf9\x9d\xde\xac\x93\x79\xc5\x38\xe3\x61\x77\x36\x7c\x69\x93\x6b\xf4\x58\xd0\x44\xcf\xdb\xeb\x57\x6b\x88\x03\xf5\x5b\x06\x75\x93\x81\x30\x1a\x08\xf3\xf6\xea\xa3\x68\xba\xb3\x5d\x26\xbc\x18\x27\x0d\x63\xa8\xc1\x53\x19\x45\x6d\x08\x9b\x3c\xea\x87\x9b\x3d\xea\xf5\xfa\x5f\xe1\x09\x3e\xdc\xbc\xd4\xb6\x39\xaa\x0f\xb7\x3b\xaa\x9b\xdb\xf9\x1b\xe0\x69\x47\x75\x95\x83\x60\x06\x95\x26\x76\xa0\xe9\xa5\xa8\xd5\xc2\x95\xbe\x79\x2f\xd4\x24\xfc\x95\xd8\xd6\xe1\x2b\x5b\xb6\x39\xe5\x09\xd8\x62\x0a\x16\xa9\xb6\x7e\xcd\x76\x6b\x0f\xe3\x64\x98\xbc\x5d\xf0\xba\xc0\x47\x63\x6b\x3b\xc0\x0c\x7c\x2a\x66\x35\xa1\x4b\x4f\x6a\x74\x77\x93\xfb\x25\x50\x91\x31\x20\xc0\xcb\x18\x1c\xd7\xa5\x04\x7f\x74\x9d\x04\x85\x1f\x10\xf7\xa8\x04\x90\x66\xb5\xce\xbe\xda\xd3\x39\x93\xf1\x37\x32\x1f\x9b\xc5\x0c\x4d\x56\x68\xf9\x41\x15\x1f\xbc\x99\x4b\x94\x63\x27\xca\x51\x0c\x06\x4b\xbe\x19\xfd\x47\xcd\x03\xfa\xe4\xf1\xab\xd7\xdc\x05\xfa\x16\x04\xb4\x31\xc0\xc1\xdb\x04\x73\x4f\x22\x33\x7d\xcb\x5d\xa0\x6f\x95\x0b\xf4\x6d\x22\xf6\x4e\x1f\x8a\x1f\xf8\x46\xed\x62\xbe\xb5\x1d\xa4\xf2\x37\x96\x11\x06\xc0\x43\xf9\x4b\xbf\xe3\x65\xe5\x6f\x7c\x2f\xf7\xb4\x1e\xaa\x9f\xea\xad\xd8\x9d\x79\x68\x3d\xe2\x57\x7b\x5b\xe2\x61\xe5\x05\x96\xd0\x3b\x07\x0f\x8d\x07\xfe\x45\xfb\xfe\x1f\x5a\x8f\xd4\xb2\x76\xec\x3f\x34\x9f\xbc\x79\x5d\x40\xf3\x74\x52\xb5\xcd\x51\x91\xe4\x85\x8d\xfa\x77\xef\x32\xbf\x57\x96\x4a\x7c\x5a\x99\xbc\xaa\x0e\x88\x2c\x20\xa7\x87\x48\x7a\x95\x0d\x37\x57\xd1\x19\xc3\xc4\xe5\x3e\x98\xa3\x87\x4c\x6e\x0a\x4e\x90\x79\xf7\x42\xa3\x85\x71\x26\x6e\x2f\x0b\x31\xfd\x8e\x95\x0d\x0b\xa0\xc6\x3c\x7c\x14\x87\x1d\xe0\x77\xeb\x8a\xbb\x35\xd7\xf3\x77\xa3\x1a\xbc\x39\xa5\xd9\x13\xba\x10\xba\x4a\x52\x15\xbc\x4d\x77\xf7\x0d\x57\x83\x15\x66\xa9\x15\x00\xac\x26\x81\x9d\xfa\x1a\x13\x4e\x69\xe8\x82\x88\x2e\xef\x6d\xc0\x32\x25\xe4\xfa\x07\x91\x4c\xc9\xa5\x6e\x82\x66\x55\x09\xd1\x9b\x35\x35\xcf\xf3\xe6\xde\x18\xe1\x3c\xb5\xd8\x3f\x82\x6f\xe9\x8e\x2b\xcb\xdc\x4c\x61\xe8\x35\x21\x95\x6a\xff\x96\x78\xbf\x8b\x78\xd1\x0b\xe6\x7d\x00\x39\x73\x71\x53\xc5\xfc\xe2\x6b\x15\x73\x71\x2e\xd2\x8a\x0e\xb9\xd8\xae\x9e\x9b\xd1\x3a\x8b\x70\xc9\x7d\x8d\xda\x33\xaa\xee\xb2\x13\x41\x23\x98\xc3\x88\xca\x24\x98\x4b\x09\x83\x45\x2e\xfe\x71\x7d\x56\xaa\x9d\x08\x8e\xc8\x4f\xe8\x19\xbd\x9b\xaf\x5c\xca\x3a\x56\x01\x62\xa3\x01\xf0\xd4\xd2\x4a\x2e\x6e\x66\x00\xe8\x4a\x14\x5f\x62\xd5\xba\xc1\xa6\x24\x0e\xc2\xdc\x94\x15\xa7\x75\xf8\x50\xcc\x0f\x95\xa6\xbf\x34\xfe\x8b\xda\xdb\x1a\x49\x47\xa7\x39\xaa\xfb\x8c\x1b\x7a\xdd\xb4\x57\x6a\xf4\x35\xcf\xd2\xc5\xa1\x3e\xc2\x58\x89\x23\xad\xb5\xbb\x49\xa6\x8b\x24\x23\x36\x35\xd4\x96\x22\x33\x28\xb4\xb2\xa7\x8d\xa7\xcc\x2d\x14\xd8\x5f\x15\x96\x46\x2f\xe9\xc6\xe3\x9b\xee\x7a\x1a\xb7\xcd\xf0\xc4\x5d\x89\x94\xfd\x17\x4c\x9f\x40\xc6\x3d\xd0\xfb\xcc\x1a\xab\x0c\x58\xb5\xde\xa1\x94\x6f\xa0\x37\x1a\xdb\x3b\x3c\x3f\xf0\x9c\x4c\xf7\xe7\x37\xe5\x10\xcf\xbf\x96\x43\xbc\x42\xe7\x82\xb6\xdd\x9f\xdf\x9c\x39\x60\xb6\x2f\xb2\x5c\x0c\x6b\x1e\x73\x9f\x16\x7b\x7b\x3c\xf7\x29\x3a\x8b\x94\xe2\x39\x12\xd7\x87\x21\x87\xb0\x3a\x59\x32\x76\xb6\x11\x50\xec\x43\xee\x9b\xe3\x6f\x71\xfa\xa2\xd2\x42\xc5\xd0\x14\x6e\xa4\x6a\xe0\x95\x45\x43\x15\xc7\x15\x5d\xe0\x52\xad\xa0\x1c\x59\xd8\x33\x10\x55\xf5\x3b\xc8\x9e\x64\x88\x16\xdb\xde\x9e\xcb\xe4\x09\x77\x55\x08\xec\x35\x0f\x31\x00\x03\xb6\x17\x66\xa3\xc5\xee\xe9\x9e\x14\x95\xdd\xc8\xf0\xe6\xa9\xda\xaa\x33\x87\x28\xb9\x17\xc7\xf5\x85\x45\xb9\xda\x8d\x64\x32\x26\x4e\xf4\x2d\x60\xe6\x12\xa3\x20\x01\x6b\xce\x65\x1d\x1d\xc2\xdf\x98\x8a\x8b\x61\xc0\xb3\x44\x4b\xc1\x71\x91\xac\xd7\x92\x75\x37\xa1\x81\x99\x68\x48\xbe\x10\x0d\x3c\x7a\xce\x46\x43\xa3\x89\xcf\xfb\x23\x37\x4c\xbf\x5a\xa3\xc1\xc4\x37\x6b\x21\x5e\x37\xe4\xe4\x68\x6c\xa7\x3a\x07\xd5\xb6\x44\x6e\x3e\xbb\xee\x76\x08\xd2\xe5\x8d\x00\xf8\x47\x05\x2f\xcd\x87\x3d\x03\x37\x99\x94\x17\x24\x8a\xed\xb1\x35\xd8\xc4\xb8\x85\x48\x4a\xa5\xea\xd8\xad\xf1\xfb\x24\x98\x3a\x46\x8a\x1a\x0c\x7d\x47\xb3\x58\xbf\xb0\xb6\xb4\x4c\xd2\xfe\xbd\xda\xbb\xbe\xf8\xcd\xb3\xce\xd9\x45\x86\xdf\x4e\xed\xbe\x72\x8a\x4f\x90\xa5\xa5\xe2\x72\xd0\xeb\x57\x73\x64\xa2\x2d\xfd\x42\x32\xa6\x8b\xd2\x6d\xa4\xfd\x0d\x03\xf8\x31\xab\x85\xfa\x10\x37\xfb\xfa\x50\x9f\xe7\x37\x51\x4a\x6a\x67\xfa\x34\xab\x30\x4e\xc6\x58\x8e\x2f\x75\x86\x8f\xf3\x18\xd4\x4d\xc4\x19\x1e\x72\x42\x98\x8e\x82\x4c\x9c\xd4\x54\xc2\x65\x03\x54\x4d\xc7\x5f\xae\x03\x2b\x25\x1d\xa1\x19\xa6\x0d\x3e\x14\x1e\x6d\x2e\x8f\x90\x5a\x59\xbf\x24\xa4\x9e\xe1\x4b\x31\x3c\xf8\x1c\x9d\x51\x4e\x42\x38\x78\xcd\xc5\xff\x37\xf5\x23\xf8\xaf\xef\xdd\xff\x8d\xbb\x0e\x7e\x49\x02\x73\xa8\x83\x5f\x12\x4c\xdd\x89\x04\xf4\xcb\xb5\x36\xf9\x2f\x1b\x6d\xf2\x5f\xb6\xda\xe4\xbf\x6c\xb6\xc9\x09\xe0\x3f\x51\x5f\x79\xc0\xbc\x77\xae\xf7\xe0\xa6\xfa\x0a\x14\x44\x7d\x11\xcf\x20\x6d\x62\x90\x0e\x9e\x01\xc4\x7d\x41\x7e\x27\x37\xd5\xf9\x4a\x1d\x87\x15\xda\xfc\xb1\x5a\xd9\x7a\xb4\x05\x75\x4b\x79\xd2\xce\xaa\x15\xce\x66\x4d\xb5\x9e\x49\xc3\x40\xd5\xce\xe9\x80\xdf\x6e\xaf\x06\xfd\x66\xeb\xa2\xde\x88\x48\x77\x5b\xd4\x1a\xd9\xc4\xe2\xeb\x4d\x08\x0b\xa9\xda\xc0\x2a\x81\x7a\x75\x6f\x76\xdd\x51\x6a\x1c\xf9\x03\xc5\xe1\x0b\x2e\x82\x2a\x54\xd0\x3b\xb2\xa3\x9e\xc9\x9f\xa5\xdd\x63\xdf\x08\x65\x55\xd8\xe2\x41\xdf\xe2\x31\x3f\x77\xc8\x57\x7e\xd3\xf4\xa0\x5c\xfc\x99\x77\x3a\x15\x74\xa7\x93\x8d\xaa\x28\x29\x90\x51\x4c\x1b\x9c\xff\x8d\xe8\x52\x19\x07\x1b\x74\x4f\xc4\xe1\x86\x4c\xc9\xe7\x04\x94\xa1\x7e\xdd\x70\x67\x84\x35\xdc\x83\x83\xf9\xd5\xaa\x59\x0a\x8d\xd3\x98\xea\xcc\x16\xba\x77\xcb\x32\xd1\x69\x95\x29\x69\xaa\x3d\xfc\x7c\x75\x5c\x64\xe1\xff\xdf\x46\xbf\xf9\x52\x5f\x6b\xf0\xb8\x7b\xb8\x6d\xf0\x9b\xf6\x4c\x08\x2a\x5a\x43\x9b\x34\xb2\x7a\x33\x5f\xb2\x37\xf1\x1f\xff\xb1\xb5\x23\x56\x9b\xa4\x0d\x91\xe9\x1f\x2a\x91\xe9\xb5\x4a\x9b\x22\xd3\x3f\xd4\x22\xd3\xad\xaa\x5f\xe1\xec\xa8\xb4\xf0\xa5\x3e\x0d\x6e\xed\x6f\x4b\x49\x89\xa7\xd7\xbc\x4c\xf9\x32\x1a\x7b\xdb\xee\xcb\xc0\x3e\x6c\xfa\xb4\x12\x03\x36\x38\x36\x1e\xdc\x4c\x57\xfb\xfb\x8e\x0d\xed\xba\x10\x8d\xf0\xd4\xcf\x98\x2c\xfa\x7a\xaf\x05\x07\x14\x33\x01\x15\xc1\x19\xd7\x34\x7e\x6d\x48\xf6\x23\xb6\x28\xfe\x4a\x02\x73\x58\x83\xbf\x12\xcc\x69\x8d\x7a\xc6\x5f\x7c\x8b\xe2\x2f\xb5\x45\xf1\x97\xb1\x37\x10\xc8\x07\xeb\x2d\x11\xbd\x7c\x81\x0f\xf8\xf5\x1a\x65\xe5\xaf\x8d\xca\xca\x5f\x5b\x95\x95\xbf\x12\x99\x1e\x3b\x78\x22\x9e\x10\x4b\xc1\x3d\x3e\xe4\x22\x03\x5d\xe5\x03\x03\x54\xb8\xde\x87\x9b\x2a\x2b\x1f\xbe\x42\x59\xf9\xf0\x37\x5d\xb6\x96\xce\xf2\xc1\xf0\x30\xe1\xfc\xbd\xe1\x83\x01\x02\x33\xbb\x19\xb0\x4c\xfa\x9a\xe8\x90\x25\xc7\xc2\xcf\x8c\x3f\x11\x16\x1e\x8a\xbc\x0f\x88\x85\x47\x0c\x4f\x1c\x3e\xfa\x4a\x38\x3f\x72\x25\xc3\xed\xb4\x34\x98\x8f\x6e\xac\x5a\x59\x69\xa3\x9b\xf2\x0b\x59\x4d\x35\xc6\x90\xf0\x2c\x6b\x5c\x3f\xb3\xcf\x81\x4a\x67\x85\xd5\xc9\xb8\x98\xd4\x78\xc9\x48\x2f\x35\x9e\x8a\x21\xc1\x6b\x30\xed\xbe\x6b\x4a\x96\x3a\x42\xdf\xb4\x84\xa9\x31\xe9\xb0\xaa\xba\xab\x07\x86\xc3\xc9\xd0\x37\xb4\x3f\x85\xcf\x18\x66\x55\x17\x3f\x83\xcf\x42\x95\x13\x09\xd6\x6d\xd0\xea\x6e\xed\x2a\x5a\xf4\x35\xe4\xfc\x0a\xf2\x6f\x8d\x44\xd0\xab\xe4\x2c\x81\x11\xe0\x3d\x92\x3b\xad\x6f\x3b\x45\xe7\xdb\x16\x26\x87\xfe\xb6\x23\x67\xd6\x3e\xfa\x5f\x19\x57\x2e\x52\x57\x34\x1b\xc3\xa0\x4e\x28\x4e\x27\xf1\xec\xcb\xb1\x24\xd5\x71\x34\x28\xc3\x1b\xe6\xb7\x89\x4b\x9a\x50\x29\x55\x79\x13\x58\x6c\x33\x58\xac\x0a\xd6\x57\x89\xb7\x47\x37\x12\x38\x75\xf9\x76\xea\x34\xd0\x6c\xf5\x42\x0d\xf3\x8c\x92\x4c\xff\xdd\x20\x8f\x1a\x61\xb8\x5e\xc4\xfe\x03\x20\xb0\x66\x08\xfe\x31\x89\x68\xce\xf5\x66\xe1\xa8\x66\xf4\xa6\x82\x91\xef\x4b\x66\x81\x09\xf6\x20\xcb\x48\xce\x65\x99\x94\x73\xf0\x4b\x6d\xbc\xab\xb7\x95\x8d\x77\x78\xcf\xb5\x45\xb9\x61\xae\xde\x90\x0c\x7c\x68\xca\x40\xf9\xc5\xde\x78\x97\x6f\x49\x9a\x9a\xdb\xee\xd6\x17\xab\x35\xf9\xc2\x2a\x51\xdf\xb4\x87\xaf\x95\x50\x02\x78\x53\x0b\x13\x50\xef\x2a\x61\x02\xf0\xfe\x1a\x89\x0d\x25\x36\x48\x6c\xfa\xb2\x51\x62\x17\xce\xef\x0c\x13\x79\xfc\x7e\x43\x49\x64\x7b\x30\x5b\x3c\x9f\xf7\x78\xd2\xf2\xe5\xcf\x9d\x56\x87\xcf\x31\x65\xe5\xee\xb4\xba\xdd\xae\x7c\xc3\x92\x59\xc7\x91\x1f\xd9\x72\xd8\x1f\xb5\x30\x15\xb8\xae\xc0\x96\x7e\xab\x85\x42\x0d\x73\xa4\xfe\xbe\x5d\x08\x35\x04\x04\x9a\xfd\xaa\x4d\x91\xef\x8c\xc6\x59\xa5\xd5\xc6\x84\x25\x9c\xea\x9d\x62\xcf\x68\xce\xdd\xd7\xad\xa8\x58\x9d\x61\xd0\x6b\xb7\xd9\x5d\x85\x0d\x7e\x25\x1e\x65\x7f\x9a\xc7\x29\x30\x04\x5c\x8c\x56\x7f\x4d\xfe\x57\x2b\x06\x49\xfb\x4f\x45\x90\x77\x51\xf5\xbc\xb2\x8a\xe7\xd5\x2b\x86\x78\x60\x84\xe7\x5f\xef\x81\xf9\xe7\xcb\x5c\xec\x58\x84\x0b\x56\x85\x7d\xe1\xfd\x3f\xe1\xd7\x0c\x54\xde\xd2\xe0\xdc\x2a\xc8\x14\x29\xfc\x7c\xde\x80\x21\x0b\x41\x14\x07\xf0\x5f\xba\x1d\x40\x44\x4f\xb2\x39\x66\x22\x0f\xe3\x16\x08\x71\x89\x46\x9c\x8a\xeb\x10\xde\xb9\xbd\x7e\x05\x88\x38\xcc\x8b\xc7\x0d\x80\x98\x34\x20\x00\x25\xfd\xe5\xf7\x9b\xf0\xe0\x4a\x04\x38\x8f\x18\x55\x3e\x47\x04\x16\x43\xa5\x2d\xa2\x4a\xbe\x13\x27\xd2\xf8\x33\x65\x25\x4c\x54\xca\x44\x0a\x55\xc7\x20\x7f\xe2\x6b\xd5\xf4\x88\x83\xa8\x83\x17\xa6\x66\x7e\x66\x24\x4a\x6c\x04\x74\x5b\x0a\x8f\xaf\x85\x72\x5b\x04\x5a\x18\x44\x2a\x26\x45\xc2\xe8\xa5\x43\x1d\x86\x06\xa3\xc3\x4b\xd9\xab\x88\x65\x1f\x57\x61\xdc\xac\x66\xda\xd7\x04\x98\xd0\xf1\x6b\x75\xe8\xa7\x94\x27\x98\xb0\x9f\xde\xc2\x0f\xf9\x4e\xd0\x50\x21\x16\xee\x6f\x2a\xf2\x83\x8b\x8b\x08\x55\xe8\x77\xc4\xb8\xde\x7d\x25\xe3\x62\x4b\x16\x16\x82\x73\x89\xdf\x8a\x13\x91\x17\x19\xd8\x90\x78\xa6\xfd\xc9\xd6\x4e\x11\x2d\x58\x4e\xac\xe9\xdd\x57\xb2\x26\xb5\x07\xfb\xee\x5a\x2e\x24\xda\xf8\xc6\xbc\x26\x80\x82\x1c\xdf\x5d\xc7\x50\x6e\x14\xe4\x28\xef\x22\x30\x1a\xe7\x81\x8e\x7b\x3c\xec\xb1\xda\x51\x43\x7e\x32\x33\x68\xa7\x3a\xa0\x8d\x4b\xb5\x3a\x9e\x51\xcf\xc7\xd5\xfe\xee\x0b\x56\x7b\xad\x09\x35\xd4\x7a\x53\xd7\xaf\x7d\x72\x60\x2a\x5c\x25\xf2\xc4\x89\xd9\x45\xd2\xb0\xa0\x13\x9d\xb1\x36\xd9\xd0\xe7\x96\x65\xbc\x35\x75\x94\xdc\xbc\xb8\xcb\xef\x39\x1a\xc9\x5c\x51\x89\x80\xc7\xf5\xc5\xe6\xc5\xbb\xaf\x58\x8c\xef\xd8\xa8\x82\x3f\xd5\x2a\xae\x31\xb1\xbc\xc0\x2c\x9a\x77\x65\xbe\xf2\xe0\xd0\xfb\x06\x0f\x69\x5e\x89\xb4\xd8\xe6\x8d\x38\xb9\x71\x96\xdd\x15\x16\x96\xbe\x22\x5d\x7d\x2a\xcb\x4a\xda\x3a\x9d\x07\xaf\xd9\xa3\x84\xd7\x53\xd0\xa5\x14\xb8\x61\xbd\xf6\xcc\xec\xd3\x0d\x17\xf2\x60\x8f\x53\x91\xd8\x05\x0b\xff\xfa\x6a\xd3\xad\x3d\x66\xca\xb9\x26\x54\xb5\xdb\x8d\x49\x2b\xb0\xc9\x11\xff\x83\x27\x09\x48\xe7\xe6\x0f\xbc\xbb\xe7\xcf\xfe\x07\x3a\x7c\xfe\x6c\x24\x7f\x34\x74\x2a\x33\x7d\x6f\x40\xc7\x4a\xe7\x0b\xc4\xd2\x4f\xc3\x65\x43\xc1\x0f\x62\xf6\xcc\x5b\x04\xa9\x38\xcf\x13\x79\xdd\x44\x5f\x55\x43\x2b\x6e\x32\x91\x3a\x52\xa7\x01\xa0\x0b\xb6\x09\x20\xe5\x7d\x69\x1a\x06\x73\x4e\xf8\xe4\x8f\x2a\xc4\xe5\x2b\x92\x68\xae\xf9\xe0\x66\x35\x37\xa3\x39\x36\xa8\xae\xb9\xd4\xa5\xd9\xbe\x49\xc7\xd0\xc7\x89\xfd\x4d\x8f\xd9\x57\xb4\x53\x88\x64\x64\x28\xd8\xc2\xe9\x59\x43\x07\xcf\x6f\x30\x06\x0c\x8d\x6e\xa8\x1a\xdf\x64\xf8\x24\x4f\xeb\x95\xc5\x7d\x06\x60\x42\xa0\x40\xd4\xae\xa9\xea\xdd\x20\x8d\x71\x0f\x1d\xe6\x17\x5a\xbc\x5a\x79\x20\x4f\x2d\x47\x17\x90\xc9\x92\x65\x6e\xf7\x43\x1a\x25\x4e\xcb\xdb\x21\xe3\xa0\xd5\x01\x09\x3a\x4d\x93\x69\x68\x0d\xea\xfa\xed\xb3\xd7\x62\x51\x1c\x9a\xfe\x78\x3c\xfc\x15\x02\x87\xf4\x9b\x96\x27\x57\x2c\x8d\xf4\x7a\xf2\x61\x63\x69\x7b\xd7\xc3\x48\xcf\xc5\x2f\xf6\x42\xcf\x38\x3f\x0b\xb7\x89\x63\x18\x0e\x85\x43\x72\xa4\xe3\x26\x52\x05\xab\xf5\xd5\x48\x57\xca\x5d\xb3\x1a\xe9\x04\xaa\xb1\x0d\x43\x78\x12\x07\x53\xf5\xed\x50\x89\xba\x1d\xca\x03\xc9\xc6\x77\x1b\x9b\x27\x55\xa2\xf3\xdc\x38\x27\xca\x77\x5b\xe7\xa0\x01\x58\x75\xf4\xfd\x71\x04\x1c\x7e\xa7\x60\x45\xcb\x8b\x95\x8d\x30\xf9\x9b\x9f\xf0\xfa\xf4\xbd\xd2\x31\x8d\xf4\xef\x0d\x13\xc6\x37\x8e\xbc\x6c\x82\x43\x14\xa9\x17\xe4\x48\x93\xd9\x13\xd0\x3c\x9a\xfa\x6d\xe2\xe8\x46\xf8\x95\x35\x1a\x68\x89\x6f\x87\x35\xb7\x61\x4d\x9d\x57\x19\x03\x26\x9a\xa2\xab\xeb\x40\x1c\x23\xb5\x21\xd9\x5b\x94\x56\xa9\xad\xaf\x9e\x2d\x46\x2d\x58\x4d\x7e\xcb\x6b\x09\xaf\x4d\xab\xe5\xdd\x88\x26\xdc\xab\x64\x84\x53\xee\xb3\x4e\x80\xd9\x02\xe8\xec\xd9\x2e\x9d\x5e\x57\x8d\xc3\xc4\x18\xd7\x89\x80\x89\xce\x93\xc6\x62\x96\xf6\x1b\x50\xf1\x11\x52\xf1\xc2\xe4\xf7\x4d\x44\x64\x66\x95\x85\xf2\xc0\xec\x57\x53\x56\xa3\xa1\x3a\xe1\xc3\xb4\xca\x31\x56\x23\x04\xef\x1e\x8c\xf0\x8e\x35\x3f\xd3\x31\x7d\x0d\x12\x8a\x72\x32\x44\x78\x05\xef\x2e\xda\x55\x80\x79\xbc\x73\x8e\x88\x06\xd3\x26\xf0\x02\x3c\x35\x2d\x07\xea\x65\x74\x72\x5a\x6c\xa3\x6e\xeb\x52\x5e\x45\x26\x8a\xca\xbb\xbc\x19\xb1\x99\x98\x59\x5b\x96\xa2\x74\x03\x56\x25\x9e\x8c\x44\xc0\x50\x9e\xf4\xff\xed\x88\xbd\xac\xad\x4e\x64\x51\x8d\x75\xb8\xd3\x97\xef\x5a\xff\xaa\xce\x62\xe1\x1e\x65\x13\xbb\x93\x1d\x58\xbb\x9b\x24\x42\x6e\x42\x15\xc7\x48\x15\xc7\xab\x02\x97\xdc\xa6\xe2\x3c\x4a\x50\x9c\x05\x8c\xf2\x43\x74\xca\x37\x94\xd5\x8b\x40\x49\x18\x4b\xde\xf8\xbb\x0d\x9c\x59\x8d\xb9\x47\x89\x26\x31\x09\x45\x33\x1e\x53\xa7\x18\x59\x0b\x5f\x04\x60\x50\xb2\x32\x21\x26\xa9\xfa\xcf\x1b\xb8\xc6\xc2\x4a\x66\xc5\xf5\xf4\x26\x7c\x1a\x36\xae\x27\x53\x95\xd6\xe5\x1b\x16\xa1\xbb\x18\xc4\x65\x34\xe6\x99\x98\x33\xfd\x56\xfa\x6e\x2d\xe1\xfa\x27\x73\x2b\x2a\x88\xf2\x65\x59\xf1\xe3\x4d\x56\x9e\xce\x8b\xca\xa4\x54\x78\x96\x6e\x40\x99\xe0\xf1\x84\x26\x4d\x47\x92\xc1\xd6\x96\x8e\xcd\x5d\x9b\xd6\x0e\xb1\x58\x51\x1c\x1b\xca\x36\xd3\x0c\x95\xc4\x39\x99\xc7\x61\xf1\xf4\x3a\xae\x73\x61\x73\x1d\xac\x53\xb0\x64\x1b\xb5\x7f\x52\x35\x84\xa8\x33\xf0\xb6\x41\x49\x5c\x2a\x25\xd1\xba\x4f\xb4\x01\x63\x00\xba\xad\x3b\x2b\xe5\x81\xee\x5c\x97\xe7\x43\x19\x6f\xea\x71\x52\x69\xcc\x3c\xff\x47\x40\x46\x01\x25\xa2\x1c\xec\xe2\xf1\xbf\xa6\x1b\x06\xf0\xe2\x01\x9d\xb4\x15\x99\x3e\x25\x62\x15\xe9\x58\x53\x3c\x63\xe1\xcf\xb1\x39\x33\xb7\x91\xca\xbf\x0f\x2c\xf1\x24\x4b\x57\xcb\x4d\x94\x7f\x62\x51\xfe\x69\xb8\x59\x6b\xe2\x7e\x4a\xe8\x62\x17\x3b\xa2\xb2\x8f\x1b\xa7\x41\x96\x16\xc9\x4a\x65\xf9\x28\x7f\xb5\x3a\xae\x5e\xc5\xaa\x82\xa6\x1a\x4d\x2c\xa9\xc9\x8d\xa0\x12\x92\xa8\xc1\xfb\x1a\xd4\xb7\x4a\xd0\x0a\xef\x71\x89\xd4\xd9\xdc\x67\x57\x42\x24\xa7\x9e\x6f\x4e\xdf\xc4\x4c\xfc\xa5\xb6\x4a\xd7\x5e\xbc\x85\x4b\x36\x29\x24\xb0\x40\x1c\x92\xba\x9f\x9a\xa0\x7b\x55\x68\x4e\x03\x45\x36\x4d\x9f\x2c\xc6\xfd\x4e\x8b\xa8\x71\x42\x54\x5b\x23\xba\x4d\xd1\x4f\x12\x5e\xf6\xda\x46\xb1\x3c\xc3\xf2\xd4\x7a\xc6\xae\x13\x03\x28\x03\xf2\xb3\x68\xb9\x91\x2a\x78\x31\xe3\xba\x4c\x12\x48\x58\xa5\xc2\x75\x6a\x6b\x7a\x03\x1a\xb1\x2a\xc6\x15\xa8\x37\xa2\xb9\x3f\x4e\xa3\xf8\x1a\xa1\x7b\x5c\x17\xba\x50\xf1\x4d\x52\x44\xd5\x4b\x21\xac\x11\xc8\xc6\x2b\xd2\x77\x13\x2e\xab\x12\x58\x84\x09\x15\xe1\x19\xbb\x06\x4b\xe2\xf6\x53\x03\x4f\x58\xe9\x2b\xf1\x84\x55\xab\x78\xc2\x77\x37\xc0\xd3\x91\xcd\x7f\xb1\xd6\x75\x48\x52\x2d\x1b\x48\x92\x86\xeb\xe6\x25\x62\x2f\x27\x0c\xbb\xbe\x9f\xce\x9a\xf4\x2c\xa1\xa7\xf0\x8b\x8e\x1d\xe3\x29\xc0\x7b\x36\x71\x2d\xe3\xed\xcc\x24\x5e\x31\x32\xc1\xd8\xb2\x0c\xb3\xf1\x39\x8f\xff\x80\x5f\x78\xcb\x5e\x28\xc2\x91\x31\x2a\x4d\xf8\x6e\xf0\x9d\x70\xa3\xc9\x97\xa6\xa1\x1b\x14\x09\xbe\x96\xd7\xfd\x51\xe1\x9b\xdf\xf2\x07\xc5\xa7\xa7\x60\xca\x62\x3d\x21\xfd\xcc\x34\xca\x78\x0f\x48\xf3\x05\x20\x61\xe6\xb5\xb8\xca\xdc\xaa\xdd\x79\x8d\xb1\x00\xf3\x6e\x92\x3e\xa1\xef\x7f\x84\x59\x02\xbd\x09\x65\x64\x80\x4d\x56\xa2\x1c\xc4\xfd\x21\x74\xdd\x09\xeb\x52\xf2\x14\x3c\xd2\xb9\xd7\x27\x6f\xbe\xdc\xa4\x69\x1d\x5d\x64\xe1\x92\x43\xd3\x52\x01\x06\x18\x96\x91\xc6\xac\xdd\x16\x3f\xba\x17\xd0\x9d\xfd\xe4\xb4\xe4\xad\x43\x42\xc9\xdf\x81\xb9\xd9\x39\x66\x2c\xd9\x99\xb1\x65\xc6\xa0\x77\x36\xf3\x76\x56\x98\x50\x46\x16\x44\x1d\x70\x27\xcd\xf4\x0b\x52\xd7\x80\x70\x77\x5e\x03\x0a\x77\x2e\xf8\x98\x76\x2e\xa2\x38\x86\x96\xa6\xa0\x26\xee\x84\x3b\x39\x50\x58\x52\xec\x30\x1c\xd3\x4e\x04\xc6\xc5\xce\x7c\x05\x40\xb2\x1d\xa4\x71\x40\x4d\x17\xbd\x17\xc6\x05\x81\x94\xb0\x5c\xdd\x9d\x42\x77\xa6\x7c\xc3\x9c\x53\xef\x6a\x1e\x47\x4d\xae\x2e\xb9\x02\xe6\x85\xa4\x2a\x52\x90\x40\xfb\x69\xb2\x79\xb7\x99\xcd\x98\x7f\x65\xdc\x9b\x68\x05\xab\xde\xc6\xf5\xf6\x2b\xd4\x11\xd6\x2b\x08\xaa\xe7\xf3\x8d\xec\x43\x96\xdd\xea\xe1\x88\x39\x10\xd7\x34\x23\x40\xdd\xde\x14\x08\xc4\xc3\xaa\xbf\x64\x8b\x33\xbd\x91\x53\x59\xbe\xd7\x46\xdf\xc0\x38\xf5\xa2\x89\xbc\x23\xc2\xad\x9c\xa5\xe4\x50\xfc\x66\x19\xbb\x1b\x82\x38\x1a\xbb\x47\x02\xa8\x42\x01\x56\x6b\xb3\x87\x82\xf7\x4f\x35\x14\x9f\xc9\xb3\xe0\xd4\xe0\x33\x79\x36\x5e\x70\x3e\x93\x2b\x3e\x23\xf3\x68\xe5\x36\xa3\xe1\x0b\x4c\xbe\xb5\x38\x4d\x23\x81\x54\x2e\x2c\x66\x6e\xa7\xe5\x23\x9d\x27\xe4\xfb\x02\x7a\x9e\xe1\x2e\xc0\x4d\x5d\xcf\x7d\xf7\x2b\xfc\x47\x7d\xb9\x12\x88\x63\x7f\xf1\x5a\x18\xe1\x52\xa0\x7d\x20\xc1\x6a\x2c\x12\x34\x02\x5a\x2c\x43\x83\x68\xbe\x76\xce\x9a\x8e\xd7\xef\xf5\x71\xbf\xce\xd8\x92\xda\x48\xd3\xf5\x85\x65\x6e\x49\x7f\x81\x65\xdf\xff\x1a\xcb\x9e\x57\x5a\x36\xd4\xe2\x48\xab\x3a\x47\x68\xc3\xde\xb8\x0e\xbd\x64\x5e\x8f\x9f\x1a\x48\xca\xf2\x80\x67\xa7\xdc\x65\x95\xd8\x71\x3b\x16\x61\x60\xf8\x3c\xa4\x5a\x51\xd4\x9c\xad\x7d\xba\xc2\x3d\xf3\xb3\x2e\x77\xd9\x3a\xc6\x65\xd7\xde\x81\xe4\xa0\x3c\x2d\x53\x87\xb9\x72\xfa\x9f\x48\x8c\x6f\x26\x01\x6b\x0a\x4d\x8e\x62\x52\x84\x71\x8d\x3c\x4c\x65\x72\x8d\xf5\xc8\x2f\xa5\xf8\x52\x43\x90\x70\xbf\xd9\xb6\xab\xa5\xdb\x92\x18\xe4\x57\x75\x97\x65\xdd\x81\xd1\x6e\x17\x43\xed\xcd\x60\xfe\x35\xf6\x21\xc5\xfb\x59\xe6\xe1\x26\x63\xcb\x80\xa5\xa0\x30\x0c\xa7\xc1\x7b\x52\x03\xb0\xd0\x5b\xa4\xb0\xb6\x64\x59\x4d\xde\xe4\x18\x87\x75\xbe\x4c\xf3\x46\xcd\x53\xe2\xec\xbe\xe9\x2a\xa2\x1a\x31\x0b\xcf\xad\x45\xc1\xbd\x1c\x94\xe3\x6d\xd2\x40\x31\x2e\x5d\xc1\xad\xf6\xad\x68\xee\xe9\x36\x5b\x8f\x4e\x9e\xb3\xae\x98\x39\xc7\xb8\x28\x8b\x09\x94\x3a\x89\x38\xe7\x4a\x7f\xbe\x53\xe7\x23\x3c\x09\x5e\x72\x8d\xa5\x85\xd4\xb1\xd7\xff\x4a\x2b\x80\x88\xe4\xb3\xad\x0b\x5c\x3b\xd8\xea\x62\x7a\x2e\x35\xfd\x84\xe3\x10\xda\xc3\xd8\xb3\x06\x26\x67\x36\xa3\x10\x01\xbc\x91\x8b\xcc\x6a\x7b\x5c\xff\x5e\xbb\xde\xcc\x38\x25\x7f\xc2\xa5\x8c\xf9\x4a\x04\x38\x83\x24\x38\xaf\x68\x8a\x1b\x03\x1f\x90\x7d\x5e\xbb\x6b\x22\x0f\x7a\x6d\xb7\x92\x8d\xdb\xd3\x00\xd4\xf3\x4a\xb8\x73\xa8\x6f\x42\x42\x00\x1f\x7b\x86\xd0\x24\x65\xec\x85\x39\x14\x7a\xf3\xc0\x6c\x84\xde\xfc\x56\xab\xf5\x7b\xad\xd6\x3b\xab\x16\x71\xc1\x55\x16\x5c\xc9\xfd\x30\x7f\xee\xe1\x18\x5e\x7b\xf7\xd3\x38\x66\x34\x0e\xff\xad\x87\xae\xa8\x0f\x85\x67\x6c\x7f\x5e\x30\x8f\xf6\xe5\x62\xe6\xf1\xbd\xbd\xe7\xf0\x03\x50\xfa\x80\x79\xc6\x76\xe7\x07\xe6\xbd\x04\x9d\x34\x9b\xf9\x8f\xe0\x17\x86\xd8\xf9\xbf\xe3\x2b\x8c\x58\xf1\xdf\x31\x2f\xca\xfd\x6f\xc8\x09\xf5\xeb\x2b\xff\x17\xb5\x21\xbb\xca\x50\x79\xba\x5a\x4f\xbc\xef\xfd\x71\xd5\xdf\x66\x6d\x44\x5b\x17\xfe\x88\x9f\x3b\x99\xce\x15\x08\x8b\x5d\x73\x5d\x64\x33\xe8\x23\x47\xc9\x48\x4e\xc8\x21\x2b\xcb\x5d\x10\x18\xf8\xe5\x65\xbb\x9d\x49\x79\x21\xf2\xc2\x00\xb3\xdb\xcd\x78\xdc\x2f\x7c\x95\x0e\xa4\x3d\x75\x55\x6c\x6f\xad\xba\x8c\x24\x74\x3a\xa7\x9c\x5c\xa0\x98\x92\x13\x04\x08\x1e\xf8\x1f\x45\x7b\x7b\x7e\xa7\x13\xdd\xcd\xe8\x8a\x4d\x10\x19\x63\x7e\xa5\xb0\x4e\xde\x3b\x50\x9d\xa8\xb6\x53\x23\x69\x0e\xa3\x01\x49\xd7\x2c\xc5\xba\x18\x69\xec\x12\xba\x3a\x58\x1d\x68\xeb\x74\xb2\xbb\x11\xbf\xcc\x13\xb3\xc9\x18\x35\xb3\x86\x6e\xc2\xed\x57\x5f\x00\x2e\x8c\xc2\xb9\x51\x98\x6b\x5c\x46\x51\x58\x35\xb8\x0d\xc3\xb7\x75\x70\xab\xb4\xa5\x2b\xae\x2c\x37\x13\x18\x7c\x19\x5a\xb2\xf7\x48\x6e\xa9\x42\xd3\x6a\x98\x0b\x8f\x19\xd3\xe3\x4a\xee\x66\xed\x36\xd3\x2c\x9c\x1a\xba\x47\x39\xb1\x87\x7b\x46\x36\xb0\x44\xb7\x19\xd7\xc2\xe6\xd4\xb9\xbf\xbd\xbd\x2f\x6d\x6c\x69\x31\x8c\x0c\xeb\x64\x68\x9f\x45\xa1\xc7\xd4\x4f\xcc\xce\xc2\x5b\xdd\x13\xad\xeb\x06\xe6\x55\x7a\x89\x02\xba\x26\xd8\x68\x28\x0c\x74\x53\x5e\x1e\xa4\x92\x9c\x56\x2a\xc3\xeb\x00\x49\x29\x17\xbe\xd0\x69\x90\x39\x29\x92\x53\x08\xff\xd1\x29\x3a\x95\x0b\x39\x1a\x06\x2b\xcc\x67\xfe\x9d\x93\xc0\xb7\x51\xdf\x47\x29\x60\x78\x06\x1b\x21\x34\x2e\xd1\xdc\x79\x8b\x97\x3f\xeb\x4f\x33\xd3\xed\x6f\x7f\x3a\x37\xe8\xe2\xfd\xfb\x56\xe7\x1b\xfb\xf3\x62\xeb\x32\x61\x1d\x27\xa1\x88\x2a\xd7\x5e\x2a\xc2\xd7\x8b\x8b\x85\x12\xa5\xc2\x1a\x50\x49\x97\xa2\x75\x9d\x92\x4f\x34\x10\xbb\xbb\x18\xa3\xc2\xef\x67\x36\x28\x54\x97\xbd\x34\xc6\xd2\xff\xbe\x37\xa4\x4c\xcf\xc3\xe0\xa7\x76\xbb\x7f\x0b\x1e\xca\xf2\x16\x68\x93\xf0\x07\xbe\xd1\xdf\x3b\x3f\x88\x1f\xdf\xf7\xef\xfc\x48\x3f\xa0\xf4\x8f\xfd\x9f\x0e\x40\x40\xff\x78\xd0\x3b\xa0\x3a\x3f\x1e\x88\x5a\xf0\xe3\x96\xfc\xf1\x93\xf8\xf1\xe3\x0f\xbc\xc1\x83\x83\x1f\x79\x03\xdf\xdf\x39\xf8\x01\x3f\x1a\x0b\xe0\x68\xeb\x02\xf0\x04\xb1\x8c\x27\x7c\x29\x0c\x5c\x0a\x52\xe1\xb9\xe1\xe9\xe7\x1f\x5e\x3a\x06\xe4\x4d\x02\x7d\x83\x53\xaa\x5b\x3f\xae\xfb\xdb\x2d\xc6\x01\x4d\xc3\x73\xc8\xdb\x27\x16\x72\xc5\x33\x58\x21\x1b\x01\xfa\x03\x95\xce\x01\xbb\x15\x23\xe4\x73\x3c\x6c\x8f\xfa\xdb\x8a\xae\x94\x5a\x01\xf5\x75\x3a\xe9\x24\xc8\x15\x81\x85\xba\xdf\x43\xc4\xb5\xec\x95\x61\x1f\x89\xb9\xa8\xd9\x5d\x50\xda\x2f\x1d\x8b\x2b\x80\x5c\xd7\x0b\x90\xe9\xa6\x3e\xd9\x4d\xa9\x56\x18\xae\xe5\x1b\xb6\x71\x61\x4c\xfd\xef\x36\x9d\xde\xa7\xe6\xe5\x13\x13\xe7\x0d\x90\xae\xc0\xac\x78\x95\xf3\xbf\x8e\x15\x9a\xf6\xa7\xcb\x25\x8e\xf9\x4e\xa5\xf1\xa5\x00\xe3\x8f\xa9\xc8\x1e\xe1\xb5\x8e\x8e\xc8\xd5\x75\x74\xd4\x82\x86\xac\xf7\xe8\x58\x5a\xb2\x19\x7e\x91\x95\x43\x3c\xa1\x20\xd1\x89\x26\x2a\x9d\x72\x52\xd0\xa1\xe8\xb3\xe8\x99\xaf\x30\xe1\xfb\x53\xed\x19\x69\x19\xa8\x64\x0e\xaf\x40\xf4\x61\x16\x3a\xfe\x5a\x40\x14\xec\xee\x1a\x38\xfa\x13\x87\x7e\xa3\xa6\x8c\x9c\xaf\xb3\x28\x83\x37\x7d\xf5\x98\xa5\xcb\xfb\xe8\xb3\x82\x97\x2a\x7b\x05\xb7\xac\xa9\xb5\xdd\x7e\x65\x7f\x9b\x55\x1b\x44\xa7\xa9\x6c\xe1\x53\x28\xdf\x9e\x47\xec\x42\x96\xd4\x10\x83\x92\x6b\x6e\x36\x9a\x40\xaa\x9c\x3c\x66\x47\x2a\x3d\x8d\x6c\x0f\x56\x03\x22\xf9\x4f\xa7\x3a\x6c\x63\x0f\xdc\x1c\x39\x88\x3b\xbe\x75\x80\x00\x67\x6a\xf8\x26\x2e\xe8\xb5\x31\xe2\x1a\x0e\xbc\xac\x32\x7a\x86\x8d\x32\xa3\x51\x13\x05\x75\xac\x50\x11\x85\x0f\xac\x9b\xc8\xba\x1a\x33\x59\x61\x9d\x40\xd3\xbd\x4b\x7c\xe9\x61\xbb\x83\x42\x0d\x04\x96\x69\x51\x99\xb0\x1e\xcf\x79\x2d\x8f\xa3\xc5\x69\xc2\xf0\x98\x9a\xac\xf2\x1d\xd4\x51\x91\x1b\xba\xff\xb7\xb5\x99\x51\xa8\xe5\xba\x31\xbf\x9d\x91\xaf\x2f\xb5\x72\x12\xa7\x4e\x6d\x56\x8e\x21\x89\xe3\x24\xe8\x0d\xf1\x32\xf7\x87\x09\x1a\xf2\x92\x95\xd9\x73\x8b\x49\xfb\xb2\xae\x8c\x2b\x47\xc7\xd3\x0c\xf8\x5c\xba\x17\x81\x80\x4d\x46\xa9\x1f\xc1\x60\x57\xc1\x22\x74\xc2\x06\xd2\x73\xe5\x1d\x16\x36\xfd\xc4\xc1\x74\x34\x15\xdd\xf9\x3d\x71\x87\x01\xb0\x4e\xb0\x2e\xf0\x06\xca\x10\x39\xd2\x6a\xb8\x04\x26\x9a\x77\x40\xef\x94\x4c\xeb\x14\x11\x3b\x03\x96\x9a\x23\x97\x3d\xbd\x1b\x0b\x2e\x7b\x1e\x4c\xc7\xa7\x13\x6f\x11\x9c\xcb\x8c\xeb\xcc\x3b\x81\x07\x72\x9e\x21\x13\x0a\x82\x9f\x69\x1a\xcf\x69\x27\x14\xed\xc2\x51\x3e\x3c\xe7\xe2\xdb\xcf\xef\x8a\x5f\x2e\xda\xc6\xe2\x76\x8a\x9e\xc7\xcb\x62\x00\xb0\x27\xbe\x07\xb9\xb7\xcb\xdf\xf2\x6e\x2f\xa1\x8b\x38\x5a\x44\xc4\xa9\x76\x45\xe3\xc1\xe5\x90\x6e\x32\xa0\x66\x3a\x9d\x61\x70\xe9\xef\x2e\xf0\x16\x15\x57\xe6\x1c\x87\xf9\x25\x5a\xa0\x36\x8e\x02\xfc\x28\x80\xfc\xec\xce\x82\xa3\x81\xcc\x8d\xbe\x7b\xc4\x39\x68\x10\x3c\x32\xea\x0e\xe8\xee\x77\x6c\x63\x3d\x1f\x2f\x3b\x9d\x49\x30\x93\x7c\x6e\xae\xe9\xe6\x37\xa4\x1b\x39\xd5\x61\x11\x02\x05\x5e\xad\xf5\x67\xbc\x90\xaa\xc9\x1c\x6b\xb7\xf9\x89\xab\x1d\xab\xaa\xc5\xe6\xdf\x19\x55\x5b\x98\x23\x1d\xac\x22\xe0\xbc\xa8\xb8\xbe\xf4\x37\x57\xfb\xa6\xb9\xda\x2e\xea\x0e\x8a\x99\x9b\xb5\x3d\x93\x5f\xff\x52\x98\xca\x63\xb5\xbe\x53\xed\x36\x10\x71\x56\x06\x4f\x2e\x0c\x67\xe0\xa8\x50\xa4\xc7\xf3\xa9\x61\x75\xac\x1c\x5c\xe1\xb6\x8f\x3f\x0f\x1d\xe4\x03\xae\x87\x5b\xbd\xb8\xc0\xa3\x70\x8d\x52\x12\x74\x06\x2c\x49\x77\x50\x14\x63\x36\x31\x00\xfc\xb5\xb0\x7c\x55\xd4\x1a\xac\xab\x9a\x9e\x0f\xc6\xd3\xfd\x08\x98\xd4\x88\x8e\x84\x11\xd6\x91\x63\xe1\x8f\x53\x68\x51\xc7\xc5\x51\x90\xbc\x6a\xfe\x2f\x13\x7c\x09\xed\xa0\x6e\x45\x50\xeb\x05\xde\x3b\x87\xad\xf3\x9c\x1b\x3e\xe3\xad\x17\x68\xc7\xeb\x26\xc5\xd9\xc1\xab\x26\x63\x01\x91\xc2\xf0\x7e\xf1\xe0\x79\x4a\x57\xd5\x08\x95\x89\xa1\x9e\x84\xca\x52\x83\x66\xc0\xd8\xcd\x0c\x10\x52\xb6\x30\xc0\xbe\x9a\x85\xd8\xe0\x7a\x51\xad\xad\x8a\xe1\x71\x93\x46\xd2\x9b\x00\x44\x96\xde\xae\xd1\x9e\xba\xca\x61\xa0\x82\x85\xb4\xb5\xb7\xbd\xc5\xba\x8a\x29\x53\xa4\x22\xc6\x18\xf0\x47\xec\x00\xc8\x55\xe8\x99\xa1\xbb\xae\xeb\x99\xf9\xb5\x7d\xd0\x94\x28\xe8\x29\xd2\x5a\x83\x3f\x50\x2a\xbe\xb6\x1e\xd9\x16\x15\x12\x9a\x3e\x0c\xb9\x1e\x39\x90\x37\x86\x23\x69\x0f\xa2\x21\xbf\xcc\x26\x72\x75\xe8\x87\xb6\x35\xaf\x69\xf2\x53\x63\x93\xd9\x30\xda\xdc\x64\xcc\xb8\x12\xe6\x65\xb2\x8e\xb0\xed\x0c\x92\x04\x88\x52\xba\x40\xa9\x20\x04\xba\x64\xcb\xa5\x98\xfb\x90\x51\xc2\x76\xe1\x17\x68\xb2\x3d\x6b\xad\x57\x1b\x8e\x44\xc3\x7b\x7b\x64\x09\xf2\x94\x8a\xd7\x35\x3b\xbf\x31\x89\x35\x50\x98\xdc\xc1\x32\x5d\x04\xa7\xac\x59\x47\x47\x41\xcd\x39\x50\xd2\x09\x3a\x88\xcd\xb2\xec\x35\x00\x34\x63\x15\x3f\x74\x10\xbc\x44\x5f\xb2\x61\x6c\x1a\x98\x90\xa5\x76\xc9\x57\x23\xb9\x70\x46\x27\x86\x7c\x63\x69\x2f\x98\x1d\xf2\xf8\x06\x99\xd6\x80\x85\x2a\x9e\xf1\x73\x48\x06\x43\xc5\x2e\xcf\x4c\x93\x3b\x55\xab\x21\x43\x84\xa2\x5d\x14\xa2\x5d\x94\x80\x55\xc4\xf0\x67\xc8\x93\xc3\x39\x2b\x34\x8c\x46\xf8\x7f\xee\xe7\x00\x59\x8e\x2b\x06\x7f\xbc\x2c\xcb\x10\xb7\x65\x0b\x17\x77\xe9\xa1\x4a\xb0\xd2\x16\xb9\x61\xc8\x36\xcf\x89\x70\xae\xc0\xfa\xd9\x85\xd9\xfe\x03\x1d\x61\x00\x22\xcc\xba\x42\x31\xfa\x0e\xc4\xcf\x1c\x17\x59\xc8\x17\x59\x38\x90\xb7\xf7\x20\xf7\x1b\x60\x9a\xc9\x20\x1a\xbd\x4d\x9c\x15\xc6\x16\x17\xe3\xd5\xc4\x7f\xe9\x67\x28\xfb\xe0\xa7\x84\xc7\x90\x3c\x97\x0a\x79\xfc\x06\xe1\xab\xb5\xe9\x7d\x22\x1b\x92\x55\x9c\x4f\xc2\x76\x67\x98\x50\x39\x19\xa7\xc8\x72\x53\xd5\xb4\x31\xdb\x47\x95\x79\x91\x52\x60\x50\xf7\x48\x65\x23\xf2\xc8\xc1\xbc\x66\xd2\x29\xa8\xfc\x4d\xe7\xa9\xaf\xad\xfd\x6c\xf4\x81\x34\x73\x5e\xfc\x30\xc5\xdf\x6f\xc4\x31\x73\x6d\x0c\x2b\x22\x52\x37\x9c\xa1\xad\x4b\x27\x3d\x71\xb6\x00\x41\xd8\x0b\x6e\x79\xfa\x88\x69\x90\xa4\x38\x81\x52\x3f\xe5\x77\xd9\x91\xa4\xd2\xc6\x1e\xc7\x31\xe9\xb1\x74\xc7\x19\xe9\x3e\x79\xf0\x33\xcd\x94\xb1\x2d\x85\x5d\x8b\x3b\xc8\x84\x0f\xe7\xad\x54\x1f\x5c\xd4\x2b\x83\xe0\x17\x72\xe4\xec\x06\x7f\xb5\xdb\xf0\xff\x5b\x00\x68\x37\x2e\xcb\x48\xf5\xf5\xb1\x18\x4f\x27\xa3\xcf\x08\xe1\x14\x23\x3a\x23\xc0\xca\xd5\x7a\x40\xdd\x3d\x4a\x9c\x78\x74\xb5\xf6\xad\x3e\x5f\x84\x0e\x45\x4e\xa5\x30\x81\xc8\xde\x5d\x2f\x84\x5f\x68\xeb\xeb\xa9\x5c\x2a\x67\xd3\x60\x89\xeb\x14\x7d\x2e\x78\x71\x55\x50\x28\x93\x14\x1e\x95\x63\x41\x28\x11\xd0\x12\xff\x95\xbb\x9e\xb3\x1a\x31\xe6\xbf\x66\xae\x63\x5c\x85\x4d\xbb\xc6\x78\x1b\x5d\x00\x38\xcf\x08\xe7\xc0\x8b\x64\x80\xb2\x41\x66\x87\x8a\x16\xa0\x67\x3d\xf3\xbb\x8a\x28\x8c\xdc\x14\x1f\x52\xe7\xa3\xf6\x71\x84\xa6\x3f\xb8\x10\x6b\xfa\xa5\xcc\xe8\xa3\xbd\x07\x96\xbe\x60\xea\x50\xb0\xba\xc6\xe4\x64\xda\x4d\xb4\xaf\x54\xf1\x81\x30\x78\x03\x0d\xc3\x92\x0a\x83\x20\x85\x05\x9f\xa3\xdf\x50\xde\x5f\x78\xd0\xeb\x8d\xde\x84\xca\x68\x9b\xea\xa5\xb0\x82\x69\x0b\x83\x5f\x61\xae\xd1\xd6\x65\xb0\xd6\xa5\x71\x80\xdc\x44\x4a\x96\x58\x39\xb8\xa0\xd9\x98\x2e\xb9\xbb\xd2\x33\x32\x55\x53\xc1\x68\x2a\xe0\xab\xa1\x47\x67\x1c\xf3\xb1\xb8\x8c\x08\xa0\xf0\x62\xaf\xe7\xde\xed\x61\x44\xa4\xfc\x54\x17\x54\x17\x16\x1e\x74\xb8\xfd\x59\x68\xce\x1b\x27\x7e\xbd\x59\xb7\x8b\x3a\x06\xbd\xa3\xa3\x07\xda\x69\xb2\x5d\x30\x25\x82\x6f\xa1\x8b\xaf\x03\xfc\xa3\xe7\xf5\x86\xfc\x0e\xc1\xbd\x64\x18\xc1\xcb\xa8\x93\x60\x6a\x4e\x8c\xd6\x04\xfe\x08\x12\x76\x14\xf9\x9d\x8c\x17\x24\x01\xde\xc1\x84\xe8\x51\x90\x0c\x51\xa5\xcc\x86\xc3\x61\xcf\xc3\x9c\xfb\x20\x4e\xa2\x61\x42\x4e\x30\x34\x21\x58\x83\xfe\xf4\xd2\x1a\xe8\x78\xb2\x75\xa0\x72\x74\x98\xda\x4b\x90\xb6\x3d\xd0\x57\xd5\x81\x2a\xe9\x65\xb7\x96\x18\xc1\x1a\x4c\x3c\x63\xa4\x7e\x36\x4a\xfc\xc2\x3e\xc1\x61\xe8\x38\x4f\x15\xf5\x57\x58\xeb\x8d\xdc\x73\x64\x7d\x39\x28\x68\xfe\x48\xe8\x8f\x03\xa8\x06\x4e\x94\x83\xa4\x39\x89\xe0\x8f\x0b\x03\x24\xbe\xf6\x14\x9d\x78\x74\x39\x88\x5a\xf8\x2b\x6c\x78\x1a\xe4\x9a\x87\xaf\xee\x4e\x07\xae\xf4\xe9\xa1\x50\x20\xfa\x42\xee\xbf\xcd\xd1\xf7\xdc\x16\xdd\xf7\x42\x1a\xd1\xa3\xc8\x58\x82\xaf\x1b\x8b\xbc\xc9\x8d\x22\x8f\xed\x22\x4f\x1a\x8a\xbc\x68\x16\x90\xec\x3a\x2d\x96\xc4\xdf\xf3\x9c\x44\xef\x75\x5a\xec\x03\x93\x1b\xf1\xe3\x25\xa0\xd7\x24\x5c\xd1\x48\x50\x8a\x47\x19\x99\x9b\x60\x62\x60\xee\xc0\x8d\x12\x51\xd4\x6d\xb7\xc5\xac\x15\xa8\x4a\xc2\x94\x69\x4b\x09\x56\x6b\x10\x20\x0b\x7f\x69\xd8\xb7\x67\x96\x80\x52\x89\x4f\x98\xd6\xbd\x84\x66\x2e\x98\x23\xea\x23\xc2\x40\xab\x09\xcf\x5d\xbc\xb0\x40\x0a\x48\xfe\x60\x7c\xcb\xcd\x6f\x79\x59\x0a\xa1\x2a\x7f\xb0\x11\x6a\x57\x00\x3f\x6d\x42\xf9\xcf\x38\x5c\x67\x1a\x34\x0d\xf3\xb3\x66\xa1\xca\x45\xa2\x47\xa2\x91\xa1\x3b\xe5\x37\x90\x72\xbf\x0d\xa0\x2b\xc7\x12\x7d\x20\xf8\xde\x8e\xa6\xc1\x5f\x3e\x97\x7c\x40\xac\x0f\x48\xc0\x42\x55\x28\x1a\xab\xa2\x0c\xa5\x24\x14\x8d\xa1\x68\xcc\x8b\xae\xb0\x28\xc6\x61\x0c\x04\xdf\x0c\x82\xbf\xf0\x4e\x49\xfc\x73\x8a\x4f\x31\x5d\x1a\xd9\x6e\xef\xc2\x68\x77\x97\x92\xc9\x3f\xe3\x9a\xc4\x94\x7b\xa0\xc4\x9d\x6d\xb3\x60\xb9\xd9\x3b\xeb\x9d\x07\x73\xfd\x95\x55\xbe\xd2\xb5\xb7\x65\x79\xae\xce\x37\x38\x33\x90\x32\xc2\xcb\x05\x8b\xff\x1c\xcc\x5a\xf9\xa4\x2e\x57\x74\xd7\x74\xbd\xb2\x36\xdb\xb6\x09\xe9\x85\x16\xd2\x0b\x25\xa4\x17\xb6\x90\xc6\x47\x36\xa8\x09\x68\xb1\xeb\x7b\x12\x38\xf9\xe8\xff\x65\xef\xcd\x9f\xe3\x46\xd2\x05\xb1\x9f\x3d\xfe\x27\xc8\x1a\x0d\x05\x74\x25\x4b\x2c\x4a\xdd\xd3\x42\x29\x59\x41\x51\x94\xc4\xd6\x41\x35\xa9\xb3\x49\x0e\x17\xac\x42\x91\x90\x8a\x40\x11\x40\xf1\x68\x16\x1d\xfd\xf6\xde\xb5\xbd\xbe\x1d\xf6\xfa\xd8\xe7\xfb\xf6\xfa\x0e\xdf\x8e\xf0\xfc\x25\xdb\xfe\x47\xfc\x1d\x99\x89\xc4\x51\x45\xaa\xa7\xe7\xcd\xbe\x78\x1d\x0a\xb1\x12\x40\xde\xc7\x97\xdf\xfd\x7d\x8a\xbc\xd5\xc8\x2d\xad\x96\x75\xb5\x53\x58\x0a\x5f\xfd\x1e\xe6\x2b\xbc\x6a\xad\x70\x7e\xfe\x14\x64\xb2\x90\xcf\xf9\x10\x8e\x5e\x8c\x98\x27\x5f\x6c\x09\xa0\x7f\x5d\x44\x04\x71\x2b\xc1\xf6\x8f\xf7\xf6\xbc\x79\x07\x7f\x09\x1d\xce\xc7\x8e\x55\x62\x75\xba\xb8\x41\x5c\xe3\x3d\xe4\xc3\x01\x2c\x82\xb5\xc7\x8a\x3a\x79\xc5\xae\x5a\x73\xc6\xb0\xc7\x84\x61\x33\x0b\x6a\x04\xc7\x2a\x74\x7a\x70\x2b\x8e\x5d\x6f\x4b\x8c\x58\xa4\xeb\x8c\x24\x9c\x2e\xb8\xab\x61\xdc\xa8\xe7\x4c\x8b\x3f\x32\x7d\xb8\xaa\x92\xcd\xcf\xab\x9c\x06\xc2\xbf\xbb\x80\x64\x1b\x8d\x0c\x6f\xfa\x05\xc3\xfa\x7b\x00\x6d\x98\xd4\xe5\x63\xe3\xda\x5c\x5a\x42\x59\x15\x7b\xe4\x0d\x1d\x97\x28\x07\x21\x05\xc4\xe4\x28\x26\x35\x11\x78\xd7\x86\x5b\x55\x23\xce\x14\x8e\x21\x34\x77\xc1\x93\xc8\xc9\xb1\xc5\x1a\xfd\x05\x8d\x38\xcf\xb7\x3d\x25\x24\x46\xea\x31\xe4\x19\x4c\x0c\x74\x73\x01\x20\x99\x35\x86\xb1\xc2\x4d\xed\xf3\x2f\xfb\xb7\x26\xb2\x18\xa0\xdf\x9e\x88\x89\xa8\x10\x3e\xfe\x50\xe3\x9d\xd9\x8d\x13\x44\x84\xdd\x44\xcd\x68\x7b\xb5\x7c\x3a\xde\x14\x26\x9c\xe1\x47\x22\xbf\x8d\x08\xe2\x3e\x41\xad\x4b\x1c\x6c\xb3\xd1\x30\xb7\xbe\x24\x2f\xcc\xf9\xa4\xc7\x06\x70\xe7\x62\x43\xd8\x5f\xda\x75\x08\x9e\x1b\x09\x8d\xc7\x80\x25\xc3\xe4\xc2\x46\x52\xb4\x59\xcc\x02\x9d\x58\xb6\x2d\xcf\xb2\xb1\x07\xd7\x41\x2c\xd0\xd8\x89\xa3\xbc\xc1\xf2\x94\x6b\xf6\xe5\x41\xa2\x48\x32\xac\xd6\x5c\x29\x48\xe6\x21\x14\x0d\x2c\x02\x30\xf6\xc8\x09\x23\x7e\xa3\x8a\xc8\xe2\x3d\x1f\xfd\xe3\xc2\x29\x9b\x42\x69\xc4\xb8\x05\x03\xbc\x80\x08\xac\x4e\x26\x0c\x01\x55\x50\x1f\x75\xe3\x95\xe8\x5c\x5f\xd1\xb9\xba\x73\x41\xe0\x00\x88\x09\xf2\x59\xa3\x60\xc0\x50\x83\x4f\x30\x35\x85\x93\x1c\xc0\x91\x03\x10\x80\x28\x04\x4c\x91\x93\x10\x5c\x0a\x21\x15\x52\xea\x21\x77\x75\x2c\x1e\xeb\xfe\x76\x2c\xba\x46\x9f\x57\xa0\xa5\x30\x92\xf2\x98\x08\x64\x3a\x88\x88\xe9\x6e\x75\x30\x4e\xf3\x50\x62\xc8\xf9\x98\x91\x5f\x98\xa0\x79\x7e\x09\x20\xbb\x8b\x7f\x7b\x78\x1b\xc8\x1e\x53\xcc\xe3\x3d\x40\x80\x29\x1e\x40\x3e\x59\x0f\x2b\x97\x8e\xde\xb2\x05\xe9\x39\x93\xbe\x06\x64\xa6\xb0\x28\x63\x3d\xa1\x88\x8f\xb1\x04\xd5\x87\x0f\x3a\xee\x31\xb1\x3b\x86\x0a\x82\x8c\x29\xea\x47\x4d\xe7\xc7\xe2\x1d\x06\x1b\xe6\x65\x18\xf3\x32\x8c\x5d\x17\xfa\x0e\xcf\x3d\xb7\xdb\xf3\xe0\x3b\xfc\x02\xd5\xd7\x43\x10\xe1\xbd\xe6\x6c\x87\x98\x0d\x72\xc1\x2f\x7c\x5d\xc5\xbf\xf8\x89\x4a\x00\xf5\x36\x22\xae\xbd\x82\xe1\x63\x03\xc3\x87\xae\x18\x75\xa9\xa7\x09\x00\xb0\xb1\x1a\xb1\xa7\xe7\x6b\x9e\xe6\x0b\x67\xcd\xd5\x32\xe1\xa1\x75\x3f\x3f\x0d\xac\x53\x58\xa3\xc1\xac\x2f\xfc\x2d\x2f\x40\xce\x77\x5e\xf0\x7b\x0b\x3a\xcd\x3c\x75\xb9\x76\xdf\x23\xe2\x3c\x21\xfd\x95\x57\x73\x52\x65\x8a\x76\x83\x9c\x91\x4d\x20\x45\xc1\xb3\x91\x9f\xa4\xc1\xe3\x61\xec\x63\xb8\x99\x68\x4f\xfb\xea\x07\x28\xf5\x16\xed\x7f\x35\xa9\x91\x74\x7c\x5f\x5f\xd4\x09\x86\x2e\xac\x61\xa7\xbc\x2b\x71\x94\x9a\xdf\xc4\xce\x81\xef\xb8\x5f\x38\xc1\x62\xd6\x44\x0d\xb7\x5c\x56\x55\x38\x78\x9a\x11\x59\x03\xcb\x23\xc0\xe6\xe1\x2c\xa0\x0c\x13\x6e\x72\x1a\xa9\x82\xe9\x16\xc1\xf0\xac\xc4\xdc\x28\xaa\xe9\x04\x52\x4f\x37\x10\x46\x01\xd3\x3b\x1c\xe5\x7d\x31\x50\x84\x51\x80\xb7\x40\xc4\xc7\x22\x62\xc2\xc8\xa6\xa0\x14\x61\x14\xac\x20\x6d\x15\x2d\x06\x44\x1a\x05\x4c\x1a\x15\xc0\x76\xe8\x6a\x92\x21\x46\x60\x0f\x10\xbf\x99\x33\xea\x2d\x9c\xf7\x5b\x1b\xea\xde\x8c\x2a\xd4\x54\x93\x98\x8f\x60\xf0\xf3\xf3\xd6\xf0\x3f\x14\xc9\x6d\x9b\x28\xcc\xc8\x87\x30\x82\x26\x5a\xf3\x4c\x33\xe5\x8b\x9e\xf0\xad\x35\xbc\x55\x9a\xca\x8f\x48\x90\x23\x9a\x0f\xd3\x98\x22\x28\xad\xb9\x66\x48\x7e\xee\x2a\x58\x49\x37\x78\x59\xe1\x30\x2a\x95\x0d\x6c\xba\x0d\xcb\xf2\xd3\xa5\xd6\xc7\xf1\x22\x56\xd0\x46\x0d\x15\xa1\x82\x94\x5c\x99\x6c\x38\xe0\xd8\x9e\xa9\xbc\x3a\xad\xf7\x73\x65\x0b\x84\x0a\xd3\x33\x9b\x08\x47\x96\xa9\x9e\x69\xd8\x00\xc5\x6d\xf6\xbe\x8a\x9c\xbc\xe1\xe9\xb1\x18\x83\x09\xb2\x2e\x52\x44\xfd\x43\xe2\x59\x20\x1b\x03\xf9\x16\x86\x6d\x01\xc8\xcb\x18\xb7\xf4\x37\x19\xe4\x46\x22\xd5\x21\xb6\x05\xaa\x7d\x00\xd0\xea\x59\xbc\x8b\xc8\xd0\x9e\x43\x86\x91\x23\x52\x0d\x19\x12\x6b\xd8\x23\x44\xdb\xaf\xb0\x32\x06\x72\x6c\x36\x80\x02\xc2\xe3\x9d\x01\xde\x8c\x23\x9b\xa3\x01\x07\x60\xcc\x90\x6e\x04\xf4\x40\x91\xbd\x91\x38\x63\x31\x52\xec\x0d\x07\x85\x3b\x48\xe7\xd6\xe4\x36\xb7\x5b\xcf\x12\x6e\x5d\x4b\x31\x56\x65\x12\x0a\xb5\xa9\x91\x47\x7c\x67\x71\x02\xac\x50\x20\x39\xa1\x9e\xc0\x51\x85\xbd\xe9\x24\xdd\x98\xf4\x99\xe2\x07\xc8\x57\x40\x0e\x3a\xa0\xb1\x31\x72\xe2\x2d\xe5\x7f\x02\x13\xc8\xdb\x88\xe1\x6f\xdc\x6c\x7b\x21\xbb\x35\x52\x4f\x4b\x02\x6b\xb3\xc9\xac\xac\xa8\x55\xde\x89\x0a\x0a\x29\xc4\x5b\x89\x34\x99\x71\x53\x4e\x2d\xae\xa3\xcf\xfc\x5a\x83\x2d\xc0\xd5\xd2\xf2\x93\xc3\x14\xa1\x90\xdf\xc2\xe6\x35\x1a\xd1\x42\x09\xde\x6a\x72\x28\x72\x3c\xc7\xda\x90\x41\xc9\xbf\x00\x46\xf5\xb4\xb8\x6d\x14\xef\xb0\x11\x8d\x8f\x0f\x82\xc4\x12\x2b\xb2\x23\x42\xf8\xd9\xf2\x29\x7c\x36\xed\xb6\x70\x25\x57\x04\x4b\x9a\x21\xc0\x36\x24\x34\x70\x1a\x3b\x4e\xd4\x0d\x56\xa4\xef\x05\x2b\xbe\xdb\x4d\x24\x4d\x9c\x8c\xaf\xcc\x6a\xe9\x7e\x71\x67\x4e\x63\x3c\x7e\xb9\xf6\x4c\x94\xaf\x20\x00\x62\xa7\x10\xd3\x65\x09\xa5\x36\x36\x77\x10\x26\x06\x69\x5f\xc4\x86\xe8\xe6\x8f\x57\x42\x43\x99\xc0\x65\xe2\x84\xcd\xd8\xbd\xb3\x8c\x04\x6c\x44\x48\x8a\xe2\xe2\xca\x1e\x9d\x05\x45\x9e\x0c\x01\xb1\xd6\x54\x49\xda\x1d\x22\x67\x6b\x32\x21\x9a\xc5\xf5\x12\x1c\x4a\x0f\x86\xd2\xeb\x8c\xba\xa1\x1c\xc3\x58\x62\x39\xd6\x43\x38\xf6\x61\x29\xd6\x7c\xab\xfb\x86\x03\x3e\x95\x55\x6a\x30\x1b\x36\x99\xb0\x58\xd7\x59\x27\x3d\x0b\xd1\xe2\x0b\x4a\xf7\x7c\xe8\x4e\xdb\x2b\x63\x04\x91\xad\xab\xc9\x74\x2e\x4c\x5e\x87\x72\xdf\xad\xe6\x16\xb5\x86\x41\xfc\x5a\x95\xba\x57\x5f\xaa\xce\xac\xc9\xb0\x15\xb8\xe4\x97\xd3\x4a\x22\xa6\x37\xa5\x2c\xd1\x12\xe5\x62\x56\x6e\xde\xc5\x81\xed\xc4\xc2\x12\xba\x16\xdc\xb6\x19\x36\x80\xad\xa8\xea\x9b\xe9\xb7\x94\x70\x4b\xcc\xa7\x53\xdf\x50\x86\x8b\x09\x5a\xa9\xf8\xf8\x3e\xcd\x41\xce\x18\x41\x4e\xdc\x4c\x11\xe8\xf8\xa8\xcf\x39\x46\x4a\x01\x05\x49\x1d\xc3\x24\x4e\xf0\x2d\x6a\x6f\xee\x31\x97\x98\x3e\xc4\x08\x3f\x21\x33\x72\x3d\xe1\x2d\xfc\x18\x05\x6a\x4b\x08\x5b\xd3\x45\x3a\xff\x51\x89\x9d\x68\xf7\x33\xc4\x7e\xa6\x92\xb4\x61\x4c\x3f\x7b\x24\x49\x6a\x8e\x5d\x4d\x92\xf7\xb4\x3c\xc7\x1c\x99\xa1\x8c\xe1\x63\xfa\x60\x8c\x1f\x87\xcd\x14\x87\x91\x9a\x61\x10\x98\xc1\xf7\x11\x72\xbd\xb0\xa4\xd5\x65\x0b\x46\x8f\x4b\x77\x66\x69\x7f\x29\x89\x52\x17\x79\x27\x2c\xeb\x20\x34\x00\x17\xfc\xae\x2b\x00\xd9\x8e\x5c\x13\xca\x54\xcd\xb5\xa5\x31\xeb\x1b\x8d\xd9\xb1\x8c\x70\x8e\xd1\x51\xc0\x58\xe0\x9d\xe2\x63\x54\xcf\x48\x5d\x32\x70\xfd\x46\x16\x42\x80\xc2\x0a\xf7\x12\xf3\x06\x90\x97\x1f\x89\x03\x9e\x63\x4f\x96\x4c\xd9\xde\x39\xa3\xb0\x64\xf5\x62\xaf\x81\x41\xfc\xac\xd5\x08\x57\x96\xd1\x26\x32\x5c\x5c\x46\x48\xac\x9e\x96\x51\xce\x18\xae\xb4\xf9\x4b\x9b\xe7\xb4\x46\x4f\x3b\xee\x02\xc5\x0a\x50\x01\xee\x78\xf1\x25\xf4\x70\x51\x2e\xc3\x0d\x1e\xd7\x39\x11\x48\xbb\x29\xdf\xf9\x90\x29\xee\xc2\xfd\x02\x5b\x73\x61\xe1\x19\xcc\x33\x45\x74\xc4\xd8\x8e\x3e\x31\x47\xe5\x5d\x40\x39\x31\x27\x5c\x4c\xa1\x6c\xbb\x85\x1b\x03\x67\x11\xee\x8a\x31\xc5\x83\x14\x63\xeb\x22\x08\x6c\x24\x67\x38\x7d\x4d\x35\x0a\x1f\x75\x9f\xfa\xa8\xb7\xb6\x44\x94\xeb\x2d\x9b\x71\x41\x11\x9f\x5d\x0b\x97\x0d\xe8\x5e\xc5\xe9\x49\x90\x07\xe1\x04\x85\xfb\x35\x71\x7c\xbe\x5f\xfd\xb2\x4e\x45\x64\xad\xd2\x28\xaa\x25\x82\xca\xb7\x79\x88\x9e\x70\xf1\x2a\xc7\x1f\x3f\xa7\x24\x53\xb8\x1a\x7c\xbc\xdc\xb3\x6e\x4a\x6d\xa7\x16\x9b\x0a\xe9\x4a\x12\x21\x3a\x21\x52\xbe\x40\x9f\x29\x07\x8c\xa4\xf1\x94\xcf\x90\x25\x7f\xd7\x5e\x30\x6c\xbd\x4e\x85\x4f\xc0\x1d\xcb\x9e\x45\x31\x76\x6a\xc0\x49\xfb\xaa\x47\xfb\x02\x13\xd0\x2a\xac\x83\x6a\xbc\xe7\xfa\x91\x53\x2b\xfb\x3f\xaa\x9f\x89\x0a\x96\x34\x8a\x9d\xf7\xc4\x5b\x20\x35\x3a\xb3\x61\x81\x0c\x54\xc8\x20\x5c\x97\xb0\xf3\x12\x52\x0f\xa8\x3d\x19\xfd\xda\x96\x34\x45\xf9\x08\x41\x90\x65\xad\x82\xc4\x42\x75\x30\xba\xde\xb5\x10\x96\xbe\x1b\x79\xf6\x2c\x9e\x46\x25\xcd\x5d\xcd\x3a\xe1\x8d\xad\xe4\x3a\x0e\xcb\xd0\x35\x49\xf0\x28\x22\xba\x8d\xce\x42\xdd\x9f\xc4\x66\x88\x0e\xfd\x5e\x70\x14\x0f\xfb\x01\x22\x8d\xd6\x93\x88\xf3\x55\xcd\xb5\x0d\x66\x43\xb2\x99\xbd\x22\xca\xc6\x57\x20\x22\x61\x3e\x95\x94\xfb\xb0\xfc\xcc\x0c\x26\x7f\x4f\xb1\x02\x7b\x6e\x81\xc7\x1e\x11\x95\x9c\x4e\x26\xf3\xaf\x70\x8e\xf2\x53\x94\xc2\x74\x25\x78\x62\x60\x44\x39\x5a\xf1\x9c\xfb\x50\xa0\xd0\x0f\x67\xf4\x9c\x39\x6a\x0a\xe8\xc6\x39\xd0\xd5\xee\x78\x55\x6d\x7a\xd2\x7c\x54\x22\x44\x50\xeb\x6d\xe9\x16\xb7\x79\x61\x32\xbb\xc5\x8b\x59\xc7\x51\x4f\x6d\x2e\x70\x45\x57\x68\x1f\xb9\x3f\xd0\x81\x90\xa3\xb1\xba\x2e\xaa\x9a\x59\x5a\x05\x37\xa8\xd3\xae\x66\x5b\x47\x75\x2d\xb2\xe1\x0e\x66\xee\xda\x3a\xdb\xd4\x5c\xe0\x5e\x45\x3b\xf2\x28\x9f\x4b\x7b\x57\x79\x14\x3b\x54\xb6\xe9\xa2\x81\xa2\x60\xc4\x13\x2e\x5b\x98\xc3\xac\x9b\x10\x70\x49\x1e\x04\x46\x7a\x15\xd3\x5d\x9f\xb7\xab\x58\xbd\x35\xe8\x9f\x5f\x91\x94\xf3\x1e\x89\xd0\x30\xe7\xa1\x8f\x7a\x21\x91\x6c\xb0\xdc\x02\x51\xf0\xb4\xcb\xfa\xe5\x3b\x7b\x18\xcc\x82\xd4\x89\xd8\xf2\x34\xe8\xe8\x2e\x60\xf3\x09\x5e\x46\x5c\x9c\xc1\x5d\xa1\x8a\xc7\xf8\x81\x6e\x16\xa8\x1c\xee\x85\x0f\x11\x50\x78\x4b\x28\x67\x1b\xc3\x9d\x22\xa5\xf3\x72\xb2\x31\x79\x34\x59\x45\x1d\xfa\xf1\xce\xbd\x3d\x35\x6d\x0b\x0b\x6d\x29\xc7\x3b\xf7\x51\x3c\x00\x75\x53\x91\x3d\x75\xfc\x23\x31\xde\xb9\x0b\x7d\x82\x1c\xbe\xc9\x0e\xf5\x02\xc2\x1f\x01\xa4\x45\xe2\x15\x28\x91\x64\xec\xe4\x12\xbc\xd2\x32\x65\xf9\x74\x29\xd5\x0e\x8b\xad\xbb\xb0\x80\x8c\x65\x6c\xd0\xc8\x6b\xf0\x68\x47\x19\xbf\x34\xda\xc9\x39\x06\x85\x94\x0c\xce\x83\x1d\x53\x29\x73\xf5\x24\xa9\x6f\x79\xac\xc8\xd0\x52\x66\xb3\xf6\xd5\xfa\x6c\xf0\x50\x55\x7d\x51\xcb\x8a\x3a\x5e\x2c\xc1\xa0\x83\xd7\xe5\xeb\x91\xd8\x4f\x89\x46\x84\xec\xfd\x7b\x7e\xfd\x31\xa8\xdb\x3d\x11\x10\x2a\x44\x96\x10\x25\x99\xe8\x53\xe2\x8a\x8c\xca\xa2\x3c\xd7\xd2\x25\xf8\x63\xb4\x61\x37\xb0\x36\xab\x01\xbe\x28\x73\x97\xae\xf6\xa1\x7e\x5d\x64\xed\x30\x00\xe3\x93\xa4\x1f\x3b\x09\x5d\xe6\x09\x5a\x08\xc0\x19\xf4\x45\x88\xec\xb1\x80\x04\xf3\x96\x16\xc1\x4d\x20\x94\x24\xd1\xa6\x83\xd5\x60\x30\x80\xd7\x3a\x43\xd3\x21\x6b\xb8\x02\x90\xdd\xb6\x2c\x5e\x6d\x34\xd1\x1a\xd2\x3e\x6a\xca\xd8\xf7\x8c\xd9\x49\xf6\xad\x95\x14\x50\x51\xeb\x02\x7a\x31\x6b\x87\xe5\xf3\x50\xf1\x3d\x78\xb7\x46\xef\x2a\xdf\x7c\x71\x65\xf3\x41\x65\x70\xe6\xdf\xe2\x0e\x54\xb7\xc2\x3d\x17\xdf\x15\x2f\x95\x4d\x43\x6c\x33\x71\x46\x92\x80\x9e\x75\x5f\x0f\x9d\x1c\xe7\x38\xa8\xf4\x4a\xac\xcb\x03\x71\x8e\x80\xf1\xc0\xed\xac\x23\xf1\x73\xbe\xb3\x6e\xc3\xc1\x75\x82\x83\xa8\x2b\x72\x2e\x81\x34\x3b\xa7\x79\x01\xdc\x8d\x5e\xa4\xf8\x02\x51\x42\x57\xf4\x27\x93\x63\x1e\xfa\x99\x1c\x16\x2e\xf1\x35\x98\xf0\x73\x71\x46\xf7\xe7\xc1\xa2\x5c\x33\xb4\xcf\xca\x01\x17\xd8\x06\x00\x97\x05\x4e\xaa\xd8\x65\xaf\x91\x6c\xea\x2d\x1e\x20\xbd\xb4\x21\xfb\xdd\x35\x7e\xfd\x0a\x92\x84\x30\xaf\x89\x97\x90\x3c\xe7\xb7\xab\xfa\xed\x79\x27\x98\x40\xfa\x91\xf7\x49\x04\x0b\xf2\x9f\x73\xfa\xdd\x4f\xde\x23\x57\x9c\xa2\x9a\x32\x3e\xbf\x98\x6c\x2a\x01\xf6\x73\xb9\xc3\x33\xf6\x52\x6c\x88\x55\xf1\x4a\x6c\xc3\x8c\xbd\xde\x13\x1f\xe5\x66\x64\xd4\x9b\x9e\xe7\x8c\x47\x96\x8b\x9d\xf8\xce\x47\x78\x2b\x3e\x16\xd0\x95\x33\xf1\xf1\x8a\x10\xc1\x37\x72\x80\x1a\x28\xe8\x14\xe1\x08\xa5\x03\xf2\xcd\xce\xc5\x1e\xd0\x7b\x34\x4d\x59\x02\x13\x80\x86\xea\x23\x80\xd7\x0f\xce\x0d\x84\x74\x74\x12\xd5\x97\xb0\x96\xc7\xd7\xe3\xa5\xc3\xee\xe1\x64\x42\x28\x5f\x8e\x9e\x3e\x56\xdd\x7e\x23\xce\x19\x2d\x1d\xc9\x60\xe1\xa5\x18\xc0\xdf\x17\xe2\x08\xfe\x6e\x8a\x3e\xfc\xdd\x10\xa7\xf0\xf7\xb5\x38\x86\xbf\xaf\xc4\xa1\x9c\x87\x2e\x50\x4d\xe2\x42\x9a\xba\x2c\xb3\x9f\xd7\x65\x57\x96\x05\x47\x11\x4d\x38\xe6\x2b\x12\xad\x7d\x8f\x48\xec\xa5\x36\x77\x43\xa9\x76\x05\x8b\x49\x0e\x38\xb4\x96\x52\x63\xae\xe1\x45\xcd\x46\x43\x24\x31\xec\xea\x27\xb1\x13\xde\xd1\x44\x9a\xeb\x1a\x8f\x11\xb6\x4e\xcb\x86\xc5\x4b\x32\x2f\x43\xa7\xa4\x5d\x9c\x56\xf7\xb5\xd2\xbb\x31\x28\xf5\x10\xf7\x78\xda\xec\xb9\x5a\x03\x67\x88\x02\xaf\x04\xfe\x30\x29\x4d\xd2\x2b\x78\x57\xc4\x02\x9a\xc8\xcb\xe7\x19\xbd\x76\x65\x42\x80\x76\x66\x1a\x75\x50\xe8\x58\xed\x0a\x31\xe4\x95\x89\x69\x4d\xfc\x22\xd9\x60\x71\x3f\x5f\x4d\x87\x87\x39\x9d\x8e\xe0\x20\xc7\x9f\x15\x06\xab\x90\xda\x6e\x10\x29\xbc\xcd\x8b\x38\xc5\xf8\x6c\xdb\x2d\xa2\x86\x8f\x2a\x70\xc3\xa8\x03\x2c\x6c\x12\xba\x35\x2e\x6a\xb2\x4c\x55\x14\x64\x81\x1e\x7a\x84\x35\xc2\x26\x54\xb0\xd4\x07\xef\xd1\xe4\x13\x8a\x97\x99\x30\x77\x45\x6f\x11\x85\x7e\x39\xfb\x2f\x58\xf8\xa4\xf9\xdd\x89\x18\x61\xdc\x09\x95\xf5\x4a\x71\xb6\xf9\x78\x3f\x46\x53\x6a\xd8\xcb\x3b\x79\xa7\x87\x62\xc4\x1d\x27\x08\x35\x80\xe3\xf4\x3e\x72\x8e\xc4\x00\xfd\x41\x1c\x21\xa5\x9d\xc2\xcf\x7d\x38\x84\xf8\x57\x6d\xc1\xb4\x3b\xee\x2e\x79\x86\xfb\x08\x80\x26\x5d\xec\x01\xa0\x41\xc1\x4f\x20\xe5\x0b\x97\x75\x54\x80\x70\x3c\x42\x82\xfd\x68\x67\x79\x8f\x65\xae\xf0\x32\x98\x97\x8f\x48\x51\x07\x60\xc9\x23\x28\x71\x94\xe3\x59\x5d\x0b\x72\x1c\xb9\xde\x86\xfd\x44\xf3\x73\x0a\xe0\xe1\xa3\xef\x9d\xf8\x7a\xd5\x4e\x9d\x3e\x7c\xb3\x34\x92\x4a\xcb\xa1\x29\x0f\x62\x17\x65\x39\xbb\x28\xc8\xf7\xf3\x3c\xcd\xf3\x78\x5e\xf6\xd0\x70\x12\xe8\x9e\xde\xca\xb8\xa4\xec\xd1\x19\xa2\x66\x14\xf1\x8e\x2e\xd5\x2e\x06\xd4\x0e\x01\x83\xa2\xa5\x87\x72\x4b\x24\x24\x6a\x0d\xbb\x89\x33\x80\x19\x05\x28\x9c\x38\x23\x31\x20\x78\x45\xb2\x58\x14\x27\x84\x86\xfb\x73\x24\x7b\x9d\x23\x34\xb2\x70\xb0\x96\xa3\x3d\x31\x0f\x85\x01\xae\xa1\xfa\xc7\x60\x32\x89\xa8\xac\x1e\x04\x59\x89\xd2\xf4\x4d\xcf\xa3\x35\x42\xe6\x2d\xc8\xf3\x32\x77\xef\x5b\x64\xa7\x7e\xeb\xd1\xcf\x07\xc5\xb7\x6c\x66\x12\xe0\x10\xf3\x32\x6f\x69\x5e\x66\xd6\x8a\xfc\x63\x58\xcc\x80\x7e\x51\x83\xfb\x38\x48\x53\xff\x90\x5e\xa9\x24\x17\xf9\xc6\x14\x99\x97\xcd\x0c\x95\x08\xd0\x0d\x79\x5e\x65\x96\x71\x73\x51\x66\x32\x42\x1d\x68\x7b\x6f\xd4\x59\x72\xe5\x9d\x29\x0b\xf8\x46\xa9\x67\xa5\xf9\x1a\x92\xde\x00\x72\xb1\x2d\x78\x0a\xcb\x08\x6b\x35\x1f\x16\xd7\x8f\xd7\x2c\x84\x05\x23\xa5\x9d\x81\x59\xc8\x23\x99\xee\x0c\xf6\x00\xaa\x87\xdd\x23\xd4\x79\x08\xbc\x5c\x6b\xea\x88\x35\xa5\xb4\xe9\x5b\xc6\xa6\x6f\xb8\x56\x9d\xbe\x5a\xee\x3e\x2d\xf7\xb1\x38\xc5\xdd\x0a\xcd\x88\x63\x48\xc0\x1d\xae\x54\x78\xfa\xf2\x74\x61\xe1\x14\x1e\x8e\x71\xb1\xf0\xab\x59\x50\x52\xa7\xea\xe7\xbd\x1c\xc1\x31\x1f\xc9\x86\x15\x3e\x0f\xb0\x9a\x23\xce\x36\xe2\x2e\x1c\xa2\x05\x7e\xfe\x1d\x2e\x9b\xa0\x10\x6e\x0f\xb5\x2b\xe7\xe5\x05\x40\x1b\xbb\x96\x90\x43\x21\x94\x5e\x05\xb8\xd5\x6b\x10\xa8\xc3\x85\x85\x43\x1b\x16\x1f\xd6\x46\x51\x80\x36\x2e\x8a\xb6\xc4\x33\xf5\x92\x4a\xd7\x5f\xd4\x3d\xf7\xbd\x75\x1f\xf9\x34\xc8\x51\x9c\x26\x53\xb4\x21\xa9\x7a\xec\x38\x4e\xd4\x0d\x57\xc6\xde\x78\x05\x45\x8c\x68\xbc\x00\xab\x80\x3f\x31\xe2\xe8\xa1\x1c\xa3\x50\x04\x05\xdc\x96\xbc\xf8\x23\xab\xbb\x1a\xac\x35\xa0\xf5\x3d\xf0\x7b\x9f\x26\x93\x41\x6c\xae\x0e\x89\x54\xcb\x20\xee\xee\x07\x5e\x88\xc2\x2c\x55\xc8\xb3\xee\x94\x37\x95\x9a\x94\x5f\x86\xc9\xe4\x30\x29\x56\x74\x98\xa0\xc5\xa6\xc8\x6a\xeb\x79\x3c\x95\xed\xdd\x8d\x72\xd8\x5f\x14\x7d\x21\x23\x93\x38\x7c\x14\x4c\x45\x9d\xe6\x98\x2c\x2f\xf9\x48\x37\xd0\x94\x19\x3d\x5a\x48\x9f\x4d\x17\x3b\xe6\x2d\xb9\xd5\x06\xf4\x7e\xb1\xf8\x09\xcd\x47\xe1\x2d\x9a\x94\x06\x22\x6b\x02\xc1\x5c\xfa\xa8\xca\x65\xc4\x7e\x17\xc1\x62\x2e\xb0\xb8\x24\x33\x55\x0f\x5e\x46\xfd\x02\x8f\xeb\xa1\xed\x0c\x2c\x37\xaa\xc1\x4b\xae\xb0\x79\x9d\x9c\x05\x03\x5b\xb1\x6a\x60\x07\x97\x46\x41\xbd\x91\x26\xba\x41\x84\x98\xb2\x11\x55\xce\x21\x04\x3e\x8f\xc6\x19\x3d\xc3\x6f\x41\xe8\xfc\xb4\xd0\x9b\x6a\x68\xca\x9a\xad\x8d\x5c\x1c\x7b\x6b\xb3\x79\xde\xcb\x18\xea\x85\x31\x58\xd4\xcb\xf7\x15\xa4\xce\xae\x5f\x2d\x90\x5a\x9b\xb9\xd0\x00\x3e\x12\xdc\x74\xea\x60\x30\x61\x02\x89\xd3\xd4\x9f\x63\x05\x34\x7d\xf5\x9b\xaa\xdf\xb1\xfa\xed\xa9\xdf\xa1\xfa\x1d\xa9\xdf\x81\xfa\x3d\xca\x3c\x2d\xf2\x3d\x18\x0f\x06\x41\x8e\x46\x52\x3b\x51\x17\x5d\xf6\xb9\xb8\x49\x5b\x07\x17\x59\xb0\x39\x18\xa4\x41\x66\x8c\x93\x5d\x0d\xd9\x4b\x80\x9b\x0b\xeb\x3e\x66\xdc\x46\x2c\xd5\xeb\x56\x4a\x2e\x35\xc5\xa3\xac\x15\x9c\x07\x3d\x54\x07\xeb\xc4\x79\xd4\x21\xdc\x12\x3a\x5d\xa3\xcd\x7c\x62\xa6\xd4\x68\xf7\x7e\x1b\x91\xbf\x42\x5a\x04\xda\x35\x22\x43\x9d\x37\xc3\x68\x43\x9f\x3e\x50\xe8\x19\x92\xd1\x4a\xe7\x2d\x40\x15\xb7\xc0\xd5\x3e\xd4\xb4\x12\x21\xec\x56\xcb\xf0\x53\x23\x79\x5b\x5e\xa2\xd9\x24\x05\xd1\xeb\xbb\x5a\x55\xc0\x5b\x91\xf3\xd4\x27\x8d\xc3\x5c\x19\xa7\xec\x91\xac\x09\x8f\x46\x76\xf2\xc2\xf7\xa0\xfb\x2b\x8b\x6d\xb8\x3d\x7f\x03\xfd\xc6\xa8\x76\x2b\x96\xc6\xc8\x33\x5b\x44\x3a\xbf\x66\x31\x44\x95\x16\x60\x92\xeb\x4b\x17\xe4\xd1\x49\xf7\x1d\x4a\x40\x49\xd1\x08\xca\x1b\xed\xce\xfc\x24\x25\xbc\x91\xe7\x22\x23\xc2\xb0\x86\x4f\xee\x86\xba\xf8\x37\xf4\x50\x9f\x32\xac\xb9\x88\xbf\x2d\x0a\xf0\xb5\xcd\x13\x76\xc3\x34\x12\x2d\x2c\x6c\x65\xad\x2c\xc0\xe0\x01\xb0\x48\x79\xff\xa2\x5c\x03\x1c\x0a\xd8\x56\xf3\x66\x60\xf3\x6b\xa6\xa4\x51\x32\x67\x75\xee\x79\x14\xb0\x67\x4a\xbf\xd3\xb6\x8d\xf9\x60\x29\xc5\x3c\xf4\xf3\x82\xf3\xa8\x1b\x49\x8a\xe7\x3b\xd1\x9e\x52\x7c\x7f\x9f\x33\xeb\x2d\x0d\x1d\x6b\x59\x2b\xc2\x7d\xf2\xae\x62\x2f\xd5\x0b\x7f\x45\x5a\x8b\xf5\xa4\xe8\xee\x8d\xd4\xcd\x59\xe7\xd1\x52\x73\x29\x4e\x1a\x62\xcf\xa8\xf6\xda\x46\xb5\xd7\x68\x82\xf7\xdd\xcb\x95\x90\x35\x5d\x5e\x92\x73\x92\x8d\xc9\xc4\xa4\x57\xa1\xe9\x9d\xdf\x6a\x5c\xf8\x01\x94\xfb\x7a\x8f\x3e\x3b\x2f\x89\x23\x89\xd9\x3b\xbf\xfa\x15\xe9\x4e\x42\xd3\x7e\x2e\x2c\x4f\x16\x5e\x90\x2a\xdd\x32\x0a\x35\x97\xa1\xb1\x09\x2c\xcd\x0b\xc0\xd0\x5f\x6b\xae\x6a\xb0\x73\x97\xb5\x91\xf5\x9d\x9a\xe1\x0b\xfc\x03\x94\x81\x8f\x56\x76\x68\x1f\x78\x6f\x0f\xa8\x61\xe4\x20\x88\x0c\xd2\xf0\x65\xdf\xc1\x2c\xe2\x1d\xbd\xa6\xef\xc6\xf4\x0e\xaa\xfc\x72\x8f\x08\x73\xac\x0c\x92\xf8\x07\x8a\xa4\xba\xb2\xaf\xac\xca\xbe\xd2\x95\x7d\x99\x57\x06\xdf\x5d\xd2\xdd\xfc\x2d\x57\x83\x63\x97\x54\x00\xe8\x9c\x85\x97\xf4\xe6\x6b\x4d\x70\x60\xb2\x8b\x13\xe2\xc1\x75\x85\x0f\x02\x1f\x8c\x8a\x6b\x06\xa4\x09\x15\xb8\x8f\x33\x80\xc4\x0a\x5e\x21\xac\x70\x8c\xab\x00\xb8\x9f\xb5\x92\xdf\xa8\x55\xca\x24\x69\xf6\x76\xa6\x2b\xdc\x5c\x5e\x15\xac\x33\x62\xd6\xd0\x8c\xe7\x18\xab\x72\x42\x2d\x65\x76\x73\x95\x8e\x5c\x01\xa7\xb0\x17\x72\xfe\xdf\x66\x51\xcb\xab\x6c\xd8\xe3\x44\xa4\xfe\x56\x52\xd3\xcb\x92\x8a\x56\x62\x6e\x07\x8c\x37\xb8\xb9\x6c\x49\xa7\x8a\x63\x05\x1b\x55\x45\x65\xe4\x48\x5a\xd4\x6f\x51\x00\x1b\xb9\x5d\xec\x7b\x2e\xf5\xb0\x66\x87\xa2\xce\x5e\x2a\xfd\xba\xa0\x95\x8e\x47\xa3\x38\xc9\x08\x13\x3d\xa4\x63\x9e\x5b\x43\xcc\xcb\xef\x26\x93\x79\xeb\x9e\xb6\xd1\x4c\x66\x9b\x16\x71\xd6\x9a\x1b\x17\xbd\x61\x3a\x05\xed\x20\x00\x82\x25\x60\x31\x6d\xea\x10\xf0\x12\x2b\x54\x19\x66\xe5\x3d\x49\x6c\x3d\x9a\xc4\xb6\xf6\x8d\xe4\xd3\x90\x35\xb5\x2d\x6d\x88\xc4\x32\x50\x8d\xa5\x19\x34\x0a\x71\x09\xec\x87\x4a\x77\x16\x87\x1f\xb7\xa2\x38\x5a\x07\xe8\xb1\x9a\x1c\xc2\xbe\x3d\x0c\xd9\xf2\x92\x49\x4c\x32\xe7\x49\xcd\x86\xe9\x49\x94\x01\x74\x50\xd7\xec\x2d\xaa\x17\x23\xda\x9a\x77\xb2\xe7\xe6\xca\x61\x3d\xb3\x85\x2c\x05\x89\x24\xa9\x51\x87\xdf\xd9\xf3\x58\xaf\x9f\x7d\x10\x64\xde\x4b\xb2\x1e\x7d\x56\x84\x44\xa1\x5d\xb4\x90\xd3\xd2\x22\x49\x94\xf7\xa0\xa2\x5b\x13\xe5\xc1\x24\xb7\x14\xc0\xaf\xad\x24\x20\x86\x9d\xb3\x5d\xb2\x23\xe3\xed\xcb\x83\x00\xbc\xd9\xe4\xdb\x80\xed\x70\xab\xdd\x70\x3d\x74\x62\xe7\x52\x5c\x9b\x5c\x37\xc5\xee\x5c\xd1\x55\x51\x37\xd3\x4e\x5b\x3c\xe5\x4f\xc8\x76\xc6\x42\x8e\x5c\x94\x37\x20\x81\xbb\xbc\xe0\x7a\xc5\x1a\x5a\x9a\xe8\x9b\x35\x90\x80\xeb\x98\x8b\x56\x59\xe3\x06\x6e\xb7\x8d\x5c\x0b\xd4\x69\x6d\x8b\x76\x59\x7c\x52\x50\xac\x52\x3a\x28\x9b\xb1\x43\x8c\x36\x52\x5f\x47\x8d\x2f\x65\x65\xc6\x5a\x70\x22\x69\x4a\x4b\xac\x68\x29\x8c\x14\x36\x9f\xb6\xe1\x2f\x9a\x75\x12\xf2\x4f\x3b\x27\x37\xe6\x8f\xd9\x98\x3f\x26\x28\x03\xb4\xc0\x9e\x8c\xeb\x80\x4c\x2f\x29\xa1\xa1\xb6\xd3\x0d\x7d\xad\x76\x9d\xda\x29\x20\x3d\xde\xb6\xab\x2c\x06\x56\x50\xd5\x03\x06\xe7\xed\x58\xee\x44\x86\x3f\x43\xf5\x81\x4c\x16\x69\xa2\x97\x74\x53\x53\x1a\x1b\x99\xc6\xf4\xce\xc8\x4f\x25\xc5\x40\x40\xfe\x3d\xb2\x06\xee\xba\x62\x7e\x09\xe5\xa0\x85\xe2\x83\xcf\x2a\x5e\x2c\x7b\x94\x54\xec\x43\x6b\x46\x1a\x76\x51\x38\xa7\x11\x87\x79\x0b\x82\x99\xd1\x13\xcc\xc3\x35\x0d\x5d\x61\x19\x9d\x16\x5b\xeb\x17\xb6\x7f\x17\xaf\x2a\x80\xc4\xb9\xa2\xc0\x0d\x26\xbd\xd4\x26\xfb\xcf\x49\xba\x6c\xa0\x59\x6c\xed\x38\x99\xe2\x93\x45\x13\x60\x5c\xaa\x3c\x25\x87\xb3\x7a\x81\x97\x81\x76\x49\xb9\xd8\xae\xd5\x95\x8c\x5c\xf4\x7a\x14\x75\xe1\x94\x25\xcd\x88\xc2\x27\x1b\x97\x3b\x06\x29\x65\x2d\x4c\x97\xd4\x25\x43\x0d\x6f\x48\x15\x30\x20\x4b\x7a\xdf\xf3\x01\x3d\xf5\x5d\x52\xa9\x31\x24\x03\x77\x0c\x37\x94\x25\xa2\xb7\xe7\x94\xb6\x6d\xdb\x76\x5a\x97\x58\xac\xee\x0c\xce\x9a\x50\x27\xb1\xc2\xef\x46\xdb\x11\x38\x8d\x6f\x58\xc3\x21\x64\x8d\xe4\xd2\xd9\x1c\x5b\x9c\x6d\x38\xa3\xda\xb6\x22\x33\x86\x10\xca\xb0\xd9\x47\xe8\xae\x6d\xb0\xdb\xcb\x6c\x83\x0d\xef\xf8\x8c\x30\x13\xc8\xba\xc8\x97\x57\x8c\xfd\x54\x6a\xcc\x3b\x96\xd0\xbc\x03\xba\x3a\x2a\xba\x72\x1a\xc8\x04\x3e\xe5\xfa\xce\xc3\x07\x23\xd6\x57\x96\xbd\x9d\xe1\x9e\x70\x06\xdd\x6f\x32\x67\x80\x16\x65\x21\xda\xcb\xc0\xf4\xbb\x0f\x96\x78\x0a\x80\x3c\xe9\x2c\x2e\x06\x86\x03\x96\x90\x1f\x92\x81\xe3\x1c\x61\x99\x23\x2e\x83\xc0\xc7\x14\xb3\x3c\x2a\x0d\x16\x16\x06\x66\x98\xa9\x4e\xd5\xf8\x63\x38\xb8\x76\xd7\x41\x13\x8b\xed\xc2\xc6\x5f\xff\x8c\x2d\xa7\x4d\x2b\xea\xb7\x5e\x28\x9d\xe2\xde\x03\x14\x89\xac\x12\x12\xa4\x11\x9b\x6d\x7b\x27\xea\x5d\x88\x27\x40\x55\x1c\x4f\xd9\x8e\xb1\xc7\x0e\x1e\x79\x3b\xd6\xf9\x3c\x25\x63\x3d\xe6\x19\x87\x4a\x85\x1c\xab\xb2\x1d\x9c\xd6\xf9\x51\x3d\x4f\xaa\xba\x00\x28\xf0\xc5\x35\x26\x95\x0d\x40\xb3\x34\x8a\x67\x82\x05\x59\x78\xeb\x52\x55\x9f\x5e\xeb\x3d\xe5\x8a\x69\x4b\x42\xf9\xc8\x71\x48\x63\x4c\xf8\x22\x56\x6e\x44\xb5\x7d\x0a\x9a\xb8\xb5\x6b\xfd\x11\x96\x56\x46\x39\x22\x40\xcf\xab\x59\xa9\x5b\x96\x4f\x02\xb4\x0f\xc5\x36\x0b\xfe\x8e\xa4\x81\xc2\xa4\x3d\xea\x5b\x26\xe2\x21\xba\xef\x49\xc9\x0b\x0c\xaa\x1c\x19\x97\x0d\xca\xc2\x28\xcc\xb5\xe6\xc9\x48\x27\x2e\x18\x27\xae\xd9\x00\xa0\x57\x06\x00\x5b\x37\xbb\xc8\x6e\x00\xde\x03\x98\xc7\x48\x26\xea\x2e\x23\x23\xf5\x02\xdc\xdc\xfe\xd9\x6e\xe4\x29\xd7\xe4\x8b\x3f\xca\x9d\x5c\xdb\xd4\xe6\xe7\x5c\xa9\xed\xca\x15\xf2\xfa\xe6\xc5\x8b\x05\x37\x66\x5f\xc7\x6c\x07\xcd\x75\xc2\x4e\x34\x3c\x83\xc6\x41\x1c\x0f\x03\xdf\x92\xb2\x05\xac\xba\x06\x0b\xa6\xe6\x22\x71\x59\x0e\x16\x08\xba\x32\x95\xa9\x25\xea\xb3\xe9\xd3\x8e\x17\xce\x7e\xa0\x39\x11\xea\x46\xf7\x8d\xee\x07\xd4\x88\x07\x0d\xa0\x40\xf7\x80\x98\x46\x1e\x99\xb6\xd8\xcc\xa3\x57\x1a\xad\xae\x3b\x1f\x3b\x7b\x1d\x0b\x11\x5c\xea\xc0\x81\x2f\x5b\xfd\xa8\xc9\x62\x24\x1f\x1a\xb7\xb4\x9f\x91\xbc\xc3\x59\xd6\xce\x19\x2c\xbc\x95\x2d\x5e\xd5\x35\x85\x30\x5d\x92\x8f\xab\xa7\x01\x31\xc3\xf4\xbe\xb0\x04\x97\x37\x05\xb6\xaa\xc7\xa1\xa4\x71\x15\x39\x68\xa8\xeb\x0a\x3b\x2a\xe1\x65\xbc\x87\xae\xdc\x9c\xb0\x6e\x30\xca\xef\xd4\x16\x69\xaf\xd9\x88\xfa\xa7\xe2\xcd\xbc\x88\x4e\x48\x2a\x5a\x6b\xcd\x66\x66\x74\xcc\xac\x3b\x7b\x27\x23\x30\x44\xac\x30\x97\x47\x91\x74\xcf\x03\x72\xad\xa4\x9d\xbe\x9f\x93\xe6\x91\x8b\x3a\x63\xe6\x6c\xc0\x8a\x25\xc5\x0d\xf7\x32\xa9\x98\x27\x15\x70\x74\xe2\x04\x60\x2f\xc9\xe9\x36\x79\xad\x20\xf5\x2b\x62\x4c\xee\xec\xb9\x25\x2e\x01\x7b\x22\x23\x12\x9b\x38\x06\x1e\xa3\xf1\x31\x14\x01\x3c\x7e\xa7\x5d\xcb\x2f\x58\x35\x37\x26\x59\xac\xe5\x33\x6d\x3b\x40\x5d\xb2\x99\x02\xcf\xcb\xe7\x2b\xd0\xd1\x35\xb3\x82\xf5\xe9\xc7\x19\xf9\x2c\xf1\x46\x92\xeb\x01\xae\x26\x2a\xba\x5a\x2e\xb4\x48\x8a\xb1\x48\x54\x0c\x72\xa5\x7e\x56\x72\xd4\x6a\x95\x7b\x58\xa4\x7f\x54\xfc\xbc\x4e\x52\x20\xf8\x8d\x03\x33\x20\x0c\x13\x17\x66\x2e\x2e\xf8\x74\x0d\xbd\x40\x86\xea\x62\x46\xc1\x76\x62\x7f\x35\x58\x61\xc9\x0d\xac\x75\x7b\x3d\x4d\xa6\x7a\xf7\x34\x1c\xd1\x22\x11\xaa\x5d\x1d\x1a\xda\x32\xd7\x35\x29\xf8\x22\x65\xb1\x00\x12\xa9\x26\x36\x49\x79\x2a\x74\xc8\x69\x54\x01\xac\x39\x18\x56\x49\x5b\x27\xfd\xfb\xa4\xce\x43\xbf\xe3\x16\x1c\x96\x9f\xd8\x99\xa2\x8a\x53\xd8\xaa\x6f\x52\x8b\xc1\x5d\x3a\xfd\xc4\x01\xe8\xc6\x81\x77\x16\x4c\x25\x31\x58\xf1\xa0\x4e\x53\x0e\xc1\xa5\xd6\x94\xb3\x2e\x78\xb8\x9f\x9d\xa2\x47\xab\xb7\xb5\xcd\xfa\x81\xb7\x65\x9a\xb5\xca\x57\x8a\x3f\x4b\x0a\xdc\xf6\x28\xc5\x2b\x84\x00\x9c\xc5\xb7\xae\xb9\x3b\x88\x6b\x9f\xdf\x8e\xc4\xd0\x41\x5b\x6d\x49\x4c\x13\x0b\x69\x82\x34\x42\xdc\x2a\x0e\x30\x99\x24\x34\x1d\x5c\x31\x5c\x95\x0a\xbd\x0c\x15\x69\x83\xb8\x65\x9d\x9f\x48\xed\x91\xf9\x15\x71\x60\x42\xb4\x89\xcd\x63\x75\xe1\x44\x00\xfe\xe5\xbd\xd1\xd3\x0c\x0f\xae\x67\x33\xe1\x3f\xd4\xce\x57\x1a\x78\xcf\x6f\x34\x5f\xb7\x8a\xf3\x45\xb5\xad\xc7\xc5\xf9\x7a\xf2\xf9\x4b\x52\xe4\xff\x18\x7f\xe6\x81\x7a\xb6\xf7\xf1\x7b\x53\x3b\x22\xdb\x35\x18\xc9\x65\x26\x89\xcb\xa5\xc5\x1d\x1a\xe4\x6b\x60\xbd\xb2\x04\x84\xc2\x3b\x54\x67\x42\xd4\x1d\xc9\x05\x5e\xd4\x6f\xec\xcb\x48\xeb\xc1\x20\x27\x94\x31\x19\x36\x56\x0e\xf3\x65\xb5\xb8\xbf\x04\x91\x74\xb3\xd3\xbd\x2b\x16\x2e\x54\xb5\x95\xa8\x23\xe8\xac\x80\xac\xbc\x1d\xba\x66\xd1\xd1\x1e\xcc\x0b\x62\xf9\x48\x35\xd5\xf8\xb2\xfa\xae\x40\x0b\x55\x37\x63\xe0\x76\x03\x8f\x14\x1c\x54\xeb\x16\xdf\x37\xac\x5b\x9d\x01\x86\xaa\xf8\x63\x9e\xd3\x20\xb4\x97\x8d\x19\x8f\x16\xc2\x55\xdb\x62\x47\x4b\xb2\x3b\x36\x8e\xcf\xf3\x56\xb2\x6c\x66\x8b\x25\x25\x4b\x36\x86\xcb\x81\xfa\x60\xec\x97\x93\x7a\xfb\xe5\x50\x8c\x6c\xee\x6e\x98\x9f\xf7\x2a\xa7\xd4\xb1\x8f\x2d\x5b\x9d\xd2\xec\x28\x77\x14\x4e\x2e\xab\x83\xcc\xe8\x6b\x96\xed\x05\xc8\x85\xa0\xd6\xb6\xc3\x2f\xd1\x1e\x05\x28\x51\x08\xbf\xc5\xa1\x0d\x0b\x27\x8c\xe0\x5b\x19\x22\x85\x2a\x4f\xbd\x1e\xfc\xd4\x0f\xf5\x1a\x62\x68\x4b\x9b\x49\x44\x5f\x0d\x42\x93\xc9\x23\xd8\x52\xb2\x49\x2c\xde\x25\x3b\x30\xa1\x22\x34\x17\xb3\x07\xed\x6e\x60\xeb\x83\xe7\x16\x2b\x1a\x95\xb4\xb8\xc2\x66\xed\x67\x6f\xb0\x00\x05\x60\xc6\xfd\x92\xa5\x0a\xa6\x1c\x05\xb8\x82\x74\xe3\x5e\xd6\xda\xad\xd8\x9b\xcd\x0f\x2d\xe4\x6b\x8a\xb5\xc0\x67\xce\x52\x62\x66\x29\x99\x6a\x63\x09\xd3\xb2\xb2\x44\x5b\x62\xca\xd4\xb8\xa2\x4d\x31\x17\xcc\x88\x6d\x0b\xad\x34\x0f\xab\x62\xf6\x02\x62\xb2\x0b\x0b\xef\x63\x67\xe0\x8a\x31\x25\xc6\xa8\xb2\x34\x90\x47\xd2\xe2\x72\x84\x8e\xc1\xf2\x16\x9d\xa3\xd4\x71\x17\x87\xa4\x69\xb4\xb4\x82\x4e\xef\xa3\x15\x18\xaa\x2e\xac\xc6\x72\xd4\x51\x95\x28\xa5\x23\x2c\x84\x8e\x86\x54\xb7\x51\xd9\x4c\x0c\x26\x13\x74\x40\x95\xca\x91\x54\xcc\x25\x62\x71\x0c\x64\x0c\x97\x54\x81\x3c\x89\x0b\xdd\x54\x15\x3b\xc7\x93\xc9\xe9\xbc\x22\x11\x6f\xda\x42\xbe\x82\x8e\x72\x23\x99\x33\x2f\x86\x5c\x07\xeb\x7b\x0a\x80\xcc\xa8\xe9\x06\xf7\xe1\x21\x7a\xa7\x22\x73\x33\x9e\x83\xc3\x85\x85\xf9\x01\xbb\x63\x81\xda\x0f\xa1\x81\xbe\x34\xb0\xe4\x74\xd1\x19\x2e\xf6\x91\x11\x07\x93\x93\xa0\xe3\xbd\xd3\x8e\xdf\x75\xc6\x24\x74\xa4\x19\x42\x65\xab\x61\xa9\xa7\xae\x87\xfd\x1c\xe3\xc8\x63\x44\xfd\x8d\x17\xb8\x85\x85\x41\x77\x20\x69\xe0\xde\x80\x83\xe7\xa0\x5e\xb3\x9a\x23\xb4\x1d\x8b\xc8\x1d\x22\x60\xd9\xa5\x1a\xc5\xbc\x3f\x99\x94\x27\x40\xf4\xe8\x2e\x22\x45\x71\xd2\xa2\x1c\x88\x23\xe8\xce\x12\x0c\x10\x88\xe1\x63\xa5\x58\x78\xa3\x3d\x4b\x9a\xc0\xf6\xcd\x85\x0e\x35\x80\x54\x52\x8a\x5f\x50\x13\x54\xd7\xe6\x25\x25\x35\x01\xe8\xe7\x21\x09\xb0\xfc\x3e\xa0\x1c\xd0\x62\xe3\xd8\x3f\x7f\xe7\x87\x19\x6a\x77\xc1\x28\xf0\x18\x46\x2d\xf5\x8e\xb4\x32\x5d\xe8\x51\x23\x4b\xfc\x70\x88\x38\x4a\x48\x11\xfd\x5a\xfa\xd9\x3b\xce\x65\x17\x40\x1b\x00\x1a\x8c\x6a\xa4\xb6\x18\x63\x26\x0c\x83\x16\x82\x5a\x2d\xd7\x60\x0a\x0c\xb3\x0e\x23\xaf\x74\xbe\x71\xd0\xfa\x97\x22\xad\x0b\x32\xa4\xb5\x8f\x26\x10\x6d\x89\xe2\x88\x85\xe4\xd3\x3b\xce\x83\x13\x71\x58\x6d\x4d\xd0\x67\xc5\x62\x39\x9e\x90\x52\xf0\x6d\x1f\xb6\x54\x6e\x8f\xc1\xcd\x11\x5a\x3f\x0e\x5b\x6b\xd4\xb6\x45\x65\xf5\x42\x45\xce\x7f\x8e\xbb\xcf\x0a\xb4\x99\xcf\xea\x81\x8c\x05\x52\x86\xa1\x45\x17\x00\x50\x5c\x2e\x90\x67\xa3\xd9\x2b\x30\xad\x23\x01\xb2\x0f\x94\x53\x5a\x6d\x42\xdd\xf6\x0c\x88\xb6\xfa\x99\x73\x13\xf3\xc5\x50\xb2\x29\xa8\x42\x0b\x4b\x17\x29\x9a\x61\x9d\xc7\x96\x68\x27\x68\x26\x7b\x65\xd5\xa7\xa5\x5c\x9d\x34\xb7\x39\x8a\x95\xfe\x50\xbb\xee\x23\x99\xf8\xea\x1c\xcb\x53\x73\x90\x11\x70\xcc\xda\xe0\x24\x9d\x0b\x9a\x4a\x8e\x97\xb0\x96\x27\x99\x3b\xf9\xdc\xb3\xc4\xc8\x32\x7d\x44\xd9\x62\x51\x5c\x0d\x7b\x15\x06\x7f\xd0\x72\xdb\x71\xcd\xad\x16\x0a\xa6\x26\x47\x25\x9c\x6e\x1e\xf9\x0b\x9f\x01\x2c\xf4\xbe\x25\x30\xda\x45\x07\x3f\x9e\x86\x09\x89\x6c\x28\x90\xc0\x27\x7c\x7e\xde\xc0\x08\x2f\x81\x56\x4a\x00\x00\x3f\x1b\x10\x00\x88\xd7\xbb\x4c\xe7\x86\xd3\x0f\x0f\x0a\x7e\xa0\x8d\x02\x3c\xe9\x9c\x32\x14\xea\xf6\x7b\x67\x6f\xd0\x7e\x11\x15\xca\x31\xab\xd3\xd8\x0b\x10\x17\x80\x3f\x7c\xf9\xef\x64\x7b\x62\xc7\x76\xeb\x7f\x5a\xc5\xe1\xa6\xb1\xf3\x0c\x26\xd2\x45\x06\x9e\x57\xaf\xc2\xa7\x78\x7e\x8a\xc9\x07\xa9\x7a\xbd\x03\x65\xd2\x05\x39\xb4\xa7\x65\xab\x4f\xc7\x65\x34\x28\xa8\xab\x25\xa0\x5a\xb0\xeb\xba\x96\xf9\xa5\x02\x72\x73\x68\x1f\x6a\x8e\xd2\xf3\x8e\x2d\x61\x72\x35\x0a\x29\xdf\x5a\x82\x2c\xbb\x40\x46\xd7\x00\x47\x81\x9b\x6f\xc3\xfd\x58\x29\xf9\xad\x25\xe4\xaa\x36\x65\xe7\xfc\x60\x09\x67\xac\x9c\x14\x86\x8a\x63\x48\x47\x71\x3f\x78\x0d\xe3\x5a\x58\x28\x97\xce\xc3\x4b\xaf\x0f\x03\x04\x0d\x0d\xa4\x55\x2d\xc9\x8d\xdd\xb4\xf1\xdb\xb7\xe4\xa9\xa1\x6a\xd5\x09\xa2\x82\xc9\xad\x18\xfd\xd0\x37\x74\x75\xda\xe2\xf0\xaa\xae\xdb\x35\xec\x52\x6f\xbe\x9e\x20\x3a\xb7\xb6\x0a\x89\xcf\x66\x2e\x2d\xf2\xa5\x23\x72\xc6\x67\x7c\xf2\xb9\xd6\xd4\x06\x8a\x3c\x89\xba\x2c\x87\xf4\xb6\x72\x35\x5e\x84\x98\xda\xbf\x29\x10\xe5\xf3\x16\x05\x79\x56\x9d\xe8\x2a\xed\xaf\x55\xe4\x8b\x8b\x70\xcb\x12\x58\x84\x16\x55\x38\xdd\xa5\x38\x8a\x7e\x8a\x91\xc2\x2c\xce\xd6\x96\x35\x1b\x3c\x14\x56\x8a\x8f\xa5\x26\x7d\x95\xab\x3d\x5b\x1d\xaf\x48\xcf\xcd\x93\xf8\xf6\xfa\x79\x54\xca\x52\x34\x9f\x6d\x14\x82\x69\x93\x6a\x04\xc6\x29\xfb\x04\x61\xa7\x8e\xa9\x99\xe3\x14\xb7\x15\x7c\xa8\xb8\x96\x37\x1e\x1b\xd9\xc1\x88\xcb\x0e\x3c\x00\xe8\x93\xdf\x90\x54\x8e\x99\x73\x8a\x0c\xd4\x3d\x41\xbe\x3c\xa8\x5e\xbd\x3a\xab\xec\x9f\x12\xf1\x2e\xfb\xc8\x6e\xdb\xeb\xf2\x3a\xa4\x85\x21\x93\x04\x4b\x78\x52\xbb\x51\xdb\x9e\xbd\x46\x4f\xba\xdf\xc6\xac\x9a\xf8\xbd\x79\xeb\x7a\xbc\xce\x2f\x8d\xd2\xa2\x25\x25\xa9\xd6\x69\xeb\x0d\xbe\xb6\x3e\x57\x95\x0e\xeb\xce\xf4\x37\x96\x24\x64\xf6\x99\xce\xac\x76\x5e\xd9\xed\xd4\xb0\xa2\xaa\xa5\x23\xab\xf4\xa3\x6a\x43\xa8\x2d\xa9\x19\x28\x80\xa5\xcf\x7f\x9f\xed\xe4\xa5\x2d\xe6\xf9\xa7\x32\xc4\xb2\x88\x9d\x97\xf6\x26\x9f\xc2\xfa\x50\x41\xaa\x80\xcc\x2e\xe9\x30\xad\xda\x15\x93\x83\x7f\x52\xdd\xb2\x72\x3c\x2f\x5d\xa5\x8f\x2c\xad\xd0\xa9\x74\x6b\xf7\x95\x8f\x96\xab\x80\x4c\x5a\x2c\x72\xbb\xa9\x57\x75\x4d\xbd\x29\x35\xa5\x37\xcf\x16\xab\x20\xb3\x76\x32\x1a\xb5\xe4\xc2\x16\x82\x21\x91\xdd\xcc\xe3\x1c\x89\xab\x9c\x42\xc6\xbd\x72\xed\x30\x2b\xf6\x36\x2b\x42\xff\x14\x35\x68\xc1\x6c\x8c\x62\xfc\x1f\x26\x75\x2c\x1e\xbd\x19\xda\x14\xce\x4e\xc9\x4e\x81\x6d\x71\x72\x18\x03\xf4\x19\x29\x4a\x26\x26\xfc\x44\x2a\x43\x8e\xc7\x47\x31\xa4\x82\xae\x6e\xda\x17\x63\xb7\xeb\xef\x8c\xf7\xb4\x6c\xd7\xc3\x07\x09\x99\x38\x91\xd6\x78\xec\x7e\xaa\x11\xb2\x0a\x1f\x6a\x8d\xef\x11\x27\x93\xa4\xd8\x66\x42\x6f\xe5\xde\x0b\x03\xda\xc5\x81\x75\x05\x6d\xf8\x75\xea\x7b\x0b\x0b\x88\x10\x77\x6c\xed\x4a\x5b\x6d\x51\x8d\xbb\x1e\x44\x46\xb9\xa6\x31\x45\x71\x55\xee\x11\xd0\x21\xd7\xca\x92\xc6\x43\x09\x43\x4e\xd0\x2b\xa5\x71\xfc\xc9\x90\x90\x35\x03\x11\x43\x9c\x4c\x4a\xe6\x3f\xa8\x14\x1b\x16\xf4\x2b\x01\xb2\xa2\xfe\xa1\x9a\x3b\x63\xb9\x68\x89\x0d\xc2\x1a\x6d\xb3\x37\x69\x45\xdf\x51\x3b\x92\x0b\x2c\xa1\x15\x29\x88\x87\x88\x1e\xef\x00\x7e\x8c\x90\xb7\x46\x48\x75\x32\xf5\x14\xd8\xea\xf5\x89\x32\x80\xfa\x43\xf4\xf8\x8b\x75\xd3\x66\xde\x33\x3e\xf8\xf1\x54\xb9\x02\x50\x87\xc4\xed\x26\x1a\x24\xd9\x07\xed\xdd\x74\x06\xa6\x52\x70\x4c\xc8\x02\x4d\x79\xb8\x9c\x27\xa7\xc4\xa6\x9f\x5d\x78\xf0\xd8\x4a\xa5\x14\x6c\x25\xc8\xb7\x7c\x4c\x06\xb3\x99\x12\x3f\xa7\x68\x21\x98\xc7\x5f\x41\x5f\xae\x21\xed\xd0\x94\x4d\x93\xa4\xdf\x45\x27\xf5\x32\x52\x9c\x6f\x7c\xc0\x6b\x11\xdf\xa1\x12\xff\x4e\xd8\x6c\xef\xb9\xc8\x6b\xbc\xbc\x22\x75\xd2\xd4\x8a\x73\x62\x47\xaa\xab\xdc\xf8\x6a\x63\x13\x00\x67\x46\xc2\x47\xf6\x1d\x70\x4f\x6b\x47\x47\x64\x7a\xa8\x82\x56\x19\x19\x65\xc1\x60\x25\x92\x61\x97\x79\xcb\x48\x67\xc4\x08\x8c\x01\x96\x6e\x22\x89\xbd\xb0\x10\x5b\x8e\x6f\x94\x97\xfd\x5c\x9f\xd9\x09\x6b\xe2\x69\x14\x3d\x70\xb2\xef\xd1\x6a\x54\x86\x67\x36\xd0\x25\xef\x87\xb4\x55\x6d\x61\x4e\x25\x47\x19\x2c\x7f\xa8\xa2\xe9\x4c\xdc\x36\xc6\x80\xb2\x0e\xc2\x28\xe8\x5b\xa7\x15\x85\x3b\x48\x15\xa0\xc8\x46\xb2\x9f\xd2\x6c\x85\x2d\xa0\x10\xe0\x65\x0f\x4e\x39\x69\x89\x50\x66\xc0\xc6\x02\xdf\x3b\x8f\x7c\xa3\xe8\x9e\x1c\xd5\x42\xae\x52\x68\xd1\x33\x56\x38\x62\xd4\xff\xc2\xb3\xe0\x7a\xd5\xaf\x01\x33\x27\x89\x38\x24\x9d\x78\x8a\x9e\x14\x48\x04\x45\x48\xd6\x20\xcb\x97\xa4\x1c\x5d\x78\x89\xb5\x2c\x61\x3c\x19\xc5\x3f\x02\x9a\xe1\x37\x40\x30\x04\xbf\x69\xeb\x05\x47\x77\xb2\xfa\x80\xa2\x12\x7d\x33\x66\xe7\xb2\x96\x17\xdb\x46\x3b\x58\x6c\x34\x1d\x27\xc6\x6b\xcc\x70\x0b\xd0\xb9\x7d\x60\xb8\x68\xef\xca\x51\x6a\x9e\x14\xaf\x7f\x02\x36\xa4\xe8\xa1\x62\x15\x2f\xb9\xad\x2c\x7e\x83\x2e\x58\xd6\x7c\x14\x73\x36\x33\x65\xa1\x6e\xeb\xe7\xbc\x9f\x56\x89\x56\x27\x5e\xcd\xc4\x51\xae\x84\xfc\x3a\x13\xd0\x43\x4b\xa6\x63\x56\x49\x95\x0d\x9a\x52\x99\xd0\x57\x65\x4a\xca\x5d\x6d\x37\xf1\x48\x5c\x94\x07\xfd\x00\x90\x12\x2d\xe6\x47\x3c\x5a\x41\x2b\x90\xa2\xb8\x0e\x16\xd3\x92\xeb\xd4\x77\xfa\xc0\xe0\x88\xdd\xbc\xff\x17\x99\xe8\xbb\x76\x84\xa8\x2c\xae\x2d\xbc\x59\x57\xf8\x05\x0c\x77\x77\xf7\xd6\x42\xa3\x50\x43\x10\x97\x07\x8d\x16\xb7\xa5\x31\xa3\xd3\x89\xaa\x7b\x01\x05\x03\x43\x09\x3b\x20\x71\xef\x2c\x03\x64\xfb\x06\x19\x3a\x00\xd6\x9e\xc4\x96\x63\xf4\x48\xbe\x8e\x9c\x46\x43\xb9\x9f\x33\x9e\x05\x62\x58\xc4\xa6\x35\x11\x51\x5c\x3a\x84\x55\x9d\x29\x57\xec\xfb\xa5\x8d\x93\xc4\xb6\xd2\x05\x2c\x17\x85\x8f\x30\x23\x11\x6d\x8a\x81\x9e\x95\xbb\x1e\x75\xfa\xf1\x5c\xf0\x9b\x65\xf6\x2e\x4c\x99\xa1\xef\x01\xfa\xb6\xcc\xe0\xb9\x73\x76\x14\x0e\x03\xcb\xc0\xd0\xea\x67\x58\xee\xa7\x6a\xce\x8e\xff\x52\xda\x13\xb9\x64\xd8\x32\x5e\xab\xdb\x0c\x71\xec\x94\xac\x43\xb3\xe0\x18\x96\x2f\x0b\xb6\x83\x2c\x03\x64\x9c\xe2\x11\x3f\xd3\x42\x53\xf6\x29\xa3\x50\x52\xd3\x8d\xe3\xc0\x01\xe4\xf4\xf2\x4a\xa0\x29\x14\x7a\x29\x39\x55\x01\x11\xd0\x40\x7f\x9c\x7f\x8e\x5a\xe1\x31\x1a\x28\xa4\x90\x47\x27\x31\x2f\x5b\x45\x8f\xd1\x2a\x1a\xa0\x25\x3a\x30\x51\x41\x3f\xd1\x4c\x32\x0b\x92\x51\x8c\x1d\x9a\x4c\x9e\xc3\x69\x92\x18\xdf\x71\xae\x29\xe7\x6e\x37\x44\x5f\xae\xc6\x8e\x13\xb5\x82\xb4\xe7\x8f\xe8\xbb\xab\x6c\xf9\x9a\x8d\x49\xa3\x39\xb0\x1f\x9c\x01\x9c\x9e\xb3\xac\xfb\x2a\xf3\x4a\xd9\xb0\x02\x94\xd8\xa9\x26\xac\x6f\xb7\x1a\xa2\x71\xd8\x20\x16\xf4\x9d\x3b\xbf\x9e\xe3\xf7\x6f\xb6\x9e\x4b\x28\xd4\x30\x4f\x9a\x2b\x6d\x5e\x78\x8d\x61\xdc\xf7\xd3\xa3\x7c\x2a\xe9\x4b\xba\xd3\x68\xce\x35\x9b\x4f\xb3\x66\x63\xaf\xe1\x36\x1b\xbb\x51\xa3\x93\x1f\x96\x7e\xd1\x35\x22\x9a\x5c\x93\xc7\x78\x8d\x9b\x90\x83\x78\xd8\xea\x47\xb0\x59\xd4\x8e\x1e\xc1\x77\x53\xfe\x63\x26\x4e\x59\x12\x10\x23\x6b\x0e\xb2\x35\x6e\xcf\x35\x77\xa3\xfd\xfd\xc0\x69\x34\xa3\x66\xc3\xc5\xa7\xdb\x0d\xf6\x4a\xe2\x9b\x3c\x1d\xe8\x46\x33\x6d\x36\x3a\x98\x55\x4d\x2c\x41\x6d\xc7\x54\xe1\x38\xfb\xfb\xd9\x9c\x9c\x83\x7a\x00\x17\x74\xdd\x39\x29\x89\x60\x9c\xeb\xce\xdd\xbe\x3d\xe7\xcd\xc1\x57\x53\xf9\x48\x8e\x9b\x06\x14\xa1\x8d\x8b\x69\xa4\xc3\x42\x01\x74\x9f\x9b\x84\xfe\xc1\x30\xe8\xa0\xd8\x04\xd6\xf3\x2c\xcc\x8e\xe6\x9c\xf8\xe0\xa3\x3b\x77\x89\x9d\x39\xc2\xa9\xb9\x82\x14\x7a\x7c\x70\xfc\xee\x51\x3e\x47\x04\x3f\x3d\x0b\xa2\x9e\x2a\x73\x0d\xf3\xe2\x98\x5e\x74\xa8\xac\x41\x7c\xa1\xe3\x0e\x34\x86\xbc\x08\x9c\x78\xd5\x8e\x73\x88\xee\x83\xf0\xe5\xdc\x64\x42\x1d\x80\x31\x62\x00\x36\x6c\xba\xd9\xc0\xee\xc2\xc8\xc4\x1c\x4e\x0b\xcc\xca\x6d\x28\x11\x77\x1b\xf8\x1c\xc0\xf3\xbe\xda\x75\x0d\x72\x4a\x04\xdd\xa4\x2f\x58\xc5\x6a\x92\xf8\x17\x39\xee\xd1\xfa\x18\x87\x11\xd4\x99\xb3\xc4\x81\xc6\xcd\x1c\xe8\xc4\x9c\x9a\x70\x28\xa6\xe8\x0c\xc3\xc1\x86\xe6\xdc\x39\x9c\x03\xaf\xc1\xdd\x81\x49\x51\x3b\x01\x0a\xc1\xf4\xf0\x74\x5e\xc8\x27\xa9\x1d\xa0\x4b\x53\x82\xb1\xd3\x13\xc7\xa6\x04\x4c\xa9\x6b\x5c\x52\x0c\xd1\xad\x11\x80\xac\x0b\xb5\x5f\xe5\x91\x38\x0b\x9d\x0b\x57\xf1\x6b\x2f\x34\xfc\xb9\xb0\xe4\x64\x71\x11\x7b\xd6\xfc\x1e\x05\xf6\x50\xdb\x0f\x55\x24\x92\x92\xa9\x8a\xde\xa6\x18\xa4\x5c\x60\x78\xf1\x26\xba\xbe\xa6\x2b\x4e\xe8\x6f\x3d\x56\xa4\x67\xea\x0e\x1d\xc6\xdb\x37\x45\x3a\xa5\x5d\x73\xef\x98\x26\xea\x3b\x80\x0d\x7b\xd4\x02\x22\x06\x85\xaa\xc7\xd7\x56\x3d\x7b\x4c\x4b\x66\x40\xf9\x9b\xa1\x6e\x89\x5e\x5b\x92\x98\xf8\x1a\x3a\x95\xbb\xf0\x1c\xf0\xa3\x8f\x1a\xfb\x9a\x87\xc6\x20\x49\xd1\x60\x35\x26\xd4\x48\x03\x40\x7a\x7c\xed\x0b\x81\xc2\xb8\xaa\x17\x5e\xdc\x21\x1e\x3a\x9e\x3a\xfe\x68\x0e\x21\xdc\x06\xcc\x43\x8f\x8f\xc3\x34\x45\x2a\x90\xbe\xa7\x4e\xd0\xd2\x6f\xd0\xcc\x9f\xdd\x80\x33\x1a\x66\xdd\x68\x70\x09\x97\x35\xa5\x33\x25\xac\x4a\x16\x6d\x66\x5d\x7b\xc5\xcf\x35\xc5\x95\xad\xa6\x99\x19\xdf\xcd\xb1\x4a\xcd\xd4\x9b\x1b\x37\x29\x54\xc8\x46\xe8\xa8\xb8\x20\x3a\xbf\x0f\x10\x38\xf0\x13\xf4\x14\xa0\xc6\x4e\x72\xca\x62\x7d\x14\xcc\xa6\x75\x38\x8c\x0f\xfc\x21\xc5\xf4\x81\x9b\x20\xd6\x86\xdc\x8e\xb6\xe4\x8e\x91\x3c\xc5\xc3\x0c\x50\x1c\x15\xb2\x73\x9b\xee\xa5\x4e\x4f\xc6\x9c\x69\xe4\x76\x5c\x74\xc7\x41\x08\x53\x67\x2c\xc7\xa6\x1d\xee\xf1\xb0\xeb\x7b\x18\x1a\x43\x2b\xdf\xe7\xa8\x15\xbb\x43\x55\xce\x3e\xc8\x0d\xbb\x75\xd5\xc6\xd0\x49\x32\xcc\x75\xec\x2a\x07\xb9\x60\x17\x26\xc0\x92\xa2\xd5\xe3\x55\xfb\x75\x78\xd5\x61\x26\xce\x0a\x3b\x6c\x74\x2d\x22\x53\xb8\xb0\x51\x42\x42\xc2\xae\xc9\xe4\x0d\xd2\x60\x05\x73\xa4\x1b\x56\x85\xbc\xb6\xee\x31\x99\xf0\xed\x97\x51\xeb\x23\x7b\x2c\x55\xe8\x94\xd9\xde\x45\x0b\xc3\xb6\xc4\x18\xf6\xfb\x8f\x81\xa3\x64\x14\x36\x09\x75\x18\x17\x04\x37\x14\xd6\xe6\x00\x29\xf1\x62\xb6\x0b\x33\xa0\x9c\xb0\xd1\xa7\x9e\x8e\x17\xdb\x51\x1a\x06\x34\x90\x2b\x46\x6b\xf2\x15\x56\x07\x68\x25\xc0\x7d\xed\xa4\x16\x08\x78\xda\x6e\xf3\x6d\x25\xa9\x41\x0a\x86\x95\x4e\x39\xb6\x14\x95\xa1\xda\x5c\x2d\xd6\x85\xab\x56\xd9\x59\x6e\xd2\xfc\xf7\xf2\x40\x53\x4a\x1a\xe6\x5b\xd2\xb0\x06\xa9\x60\x2a\x81\x38\x5c\xd4\x51\x8b\x5e\xb8\xda\xe7\x73\x8a\xee\xab\x94\xcf\x24\x74\x8a\x8b\x31\x02\x76\x86\x68\x26\x3b\xdc\x93\x23\xd4\xe0\xb0\x5d\xbe\xe2\xcb\x1a\x31\x5f\x49\x92\x1d\xc9\xa2\xfa\x27\x39\x57\x47\x5c\x4e\x83\xc7\x8a\x96\x26\x3b\xac\xb5\xb4\x34\xc9\x7a\xb7\x12\x55\xde\x48\xb0\x89\xf9\x43\x4a\x27\x1e\x79\x9e\x4d\xbd\xfc\xb2\x53\x1e\xef\x61\x47\xa3\x0d\x52\xae\x36\x0c\x58\x90\xf2\x9a\xb5\x63\x2b\x93\xe6\xf1\xa5\x2d\x6f\xfa\x46\x32\x2d\x8c\xec\x1d\xc5\xac\x57\x70\xba\xeb\xe2\xc0\xee\xc7\xb6\xd3\xf2\x7d\xf9\x2c\x2e\x85\x04\x3f\xc0\x0c\x96\xa4\xc8\xde\x8f\x14\x2b\xa9\x4b\x11\x5f\x3c\x0a\xdf\x62\xc9\x79\x6a\xb7\x7e\x3e\xef\x65\xa6\xab\xed\xee\x71\xc6\x35\x61\xce\x2f\x93\xce\x39\xe2\xdf\x56\xf8\xbe\x16\x5a\x56\x48\xea\x32\x13\xf4\xd4\x47\x7b\x50\xa4\xa0\xdd\x3b\x68\x5b\x84\x3c\xab\x29\x92\xf1\x0c\x09\x13\x13\xab\xc4\x62\xd7\xad\xd9\x47\x2a\x43\x32\x26\x43\xa5\x23\x45\xf2\x18\x93\x5c\xa5\x81\xaf\x1a\x86\xfa\x91\x7c\x17\x67\xbe\x0a\x9c\x60\xf4\xef\x95\xfb\xeb\xac\xe3\x9e\xf9\x2b\x49\x97\x1d\x45\x3a\xe4\x7d\xd3\xd2\x81\xb0\xa4\x47\x71\xce\x9c\x6f\x36\xdf\x19\x67\x38\x78\xb6\x9a\x96\x94\x69\xbb\x00\x20\x1c\x9a\x3a\xc0\xd4\xd8\x7e\xc4\x92\xad\xdc\xec\x7a\x56\x61\x51\x34\x97\xc4\x62\x19\xa2\xfb\x35\x8e\xda\x44\xb1\x48\x13\xa3\x9e\x18\x76\x8f\x02\x66\xe0\x62\x64\x5d\x0a\xfa\xe5\xa9\xd0\x24\x57\x00\x34\xba\x49\xd0\xea\x07\x03\x7f\x3c\xcc\x52\x27\x0a\x5a\x9b\x24\x29\x43\x55\x6c\x01\x5f\x46\x61\xef\x13\xbc\x15\x0f\xb1\x54\xc4\x04\xf2\x26\xf2\xbf\x08\xbd\x14\xaf\x31\xf9\x08\x68\x0b\xb1\x81\xa9\xf5\x24\x89\x13\xf1\x0a\x93\x8f\xd5\xc0\xc4\x23\x7c\x7a\xe1\x03\x1e\xfe\x09\x53\x2f\x49\x86\x23\x5e\x62\x9a\x9b\x12\xab\x98\xde\x0a\x0e\xd7\xcf\x47\xe2\x39\xa6\xb7\x49\xfe\x22\x3e\x62\x1a\x45\xaa\x5c\xed\x1b\xdc\x1d\x39\x48\x11\x8f\x63\xf9\xd2\x7e\x7e\x18\xcb\xe7\xf6\xf3\xd3\x58\x3a\x4f\xb1\x8a\x33\xb8\x28\xe3\x33\x98\xcb\xa7\x71\xab\x1f\xf7\xe8\x84\x8a\xef\x01\x46\x5a\xb9\x5b\x59\xac\x5a\x3d\x89\xe5\xe3\x18\x15\x64\x36\xcf\xa2\x57\x49\x3c\x0a\x92\xec\x42\xbc\x43\x03\xb0\xb7\xf4\xc5\x64\x7c\x86\x75\xef\x8b\x6f\xe9\xd2\x6f\xfc\xae\xd1\xcc\x62\xe7\x6d\x9c\xd3\x00\x77\x74\xce\x89\xc1\x8d\xdd\xd6\x17\x5d\xa7\x2b\x77\x77\x77\x1d\x77\x02\x97\x5c\x32\xd7\x6a\xaa\x17\x7b\xee\x9d\x43\xa4\x19\x20\x07\x62\x0a\xb7\x80\x74\xf8\x10\xcb\x17\xa1\xf3\xc1\xcc\xf6\x43\xf2\x44\x03\xe3\xf8\x10\x8b\x5b\xf4\x0d\xfe\x7e\x88\x17\x16\x90\xeb\xf8\x21\x46\x5e\x11\xdd\xef\x28\x7d\x8a\xc5\x93\x58\x3e\x8a\x5b\xbd\x20\x1c\x8a\xf7\xc4\xb0\x1c\x02\x36\xf3\x3a\x3c\x0e\xe2\x71\x26\xbe\xa1\x8f\x83\x61\x0c\xf3\xfa\x1d\x55\xf5\x1d\xcd\xe6\x61\x90\x59\xc3\xde\xbe\x38\x3e\x88\x87\xc8\x83\xfd\x0e\x00\x93\x8f\xd9\xe0\x2f\x67\x7b\xa5\x67\x6e\x73\x80\xbc\x3f\x5f\x04\xbe\x7c\xc3\xdc\x75\x11\x51\xd6\xc8\xe7\xf5\x09\x4e\x61\xbe\xd7\xcf\xb3\x20\x42\x2c\x0f\x6b\x8b\x7c\x91\xf8\x38\x97\x23\xd5\xd0\x46\x8a\x32\x85\x20\x41\x7a\x4c\x84\x54\x3a\x44\x3d\x24\x20\xfe\x21\x7b\xe8\x8b\x18\x9f\xd2\x20\xd3\xfd\xf7\xa9\x31\x16\x7c\x8b\x94\x0a\xa4\x98\xe5\x0d\xd0\x34\x5f\xd3\x64\x41\xb9\x14\xa8\x7e\xfa\x34\xc6\x4f\xef\x02\xff\xd3\x0b\x7f\x84\x4e\x03\x7c\xd1\xf3\x6d\x2d\xaa\x2c\xb9\x50\x07\x19\x32\xa3\x08\x84\x18\x7a\x5f\xdd\xd3\x15\x05\xca\x0b\x53\xe0\xa8\x99\x6e\x03\xac\x5a\x02\x88\x01\x9f\xae\x7a\x84\xc4\x24\x00\xa6\x0d\xcb\x04\x0e\xcf\xb0\xd0\x00\x9b\x4f\x44\xfe\xc2\x02\x4e\x21\x4e\x8b\x0f\x28\xef\x21\x71\x4d\x3b\xd8\x3a\x42\x30\x0d\x4c\x22\xdf\xb9\x6c\x7b\x68\x9f\x84\x1e\x38\x64\xfb\x4a\x35\x11\x71\x47\xd1\x7f\x6e\xe3\x3c\x06\xa0\x6d\x5e\x6b\x07\x34\xe8\x2b\x05\x6a\xcc\xfd\xd1\xa0\x0e\x21\xcd\xc0\x08\x95\x7c\x5a\x78\xbf\xf1\x88\x46\xbe\x18\xd0\x87\x01\x2d\x52\x2f\x09\xe0\x0c\xc3\xfb\x81\x2f\x8e\x70\xb2\xc2\xf4\x71\x18\x85\x70\xac\xfb\x94\xab\x4f\xb9\x3e\x05\x17\xb8\x7a\x7d\x5f\x9c\xfa\xb8\x7d\x8e\xfd\x73\x71\xcc\xa9\x30\x12\x87\x94\x13\xfe\xbe\x46\x1f\x0f\x78\xdc\x0e\x7d\x71\x41\x2f\xe1\xef\xa7\xd8\xd4\x09\x5f\x2e\x7c\xb1\x8f\xcd\x10\xf7\x74\x03\x4e\xe3\x01\x55\x93\xf8\x70\x50\x8f\xc5\x3a\x65\x7f\xb9\xfe\x64\xf5\xf5\xc6\xdb\xf5\xfd\x8d\x97\x8f\x37\x5e\x6e\xbc\xfe\x20\xce\xe9\xfd\xab\xcd\xed\x8d\xe2\xfb\x33\x2a\x3c\x8a\xcf\x9c\x65\x71\x77\xd9\x05\x38\xbf\xe6\xcb\x33\x1f\x7e\xb7\xf0\x97\x42\xca\x6c\xfb\xb2\xe7\x77\x7b\x7e\xeb\xe1\x87\xd7\xeb\xdb\xfb\xaf\xd6\xb7\xf6\xd7\x9f\xaf\xbf\x58\x7f\xf9\xda\x5b\x12\x2f\xac\x0a\xbe\xbc\x8b\x15\x6c\xfa\x72\xec\xf3\xc1\x82\xdd\xf2\x1a\x45\x74\x62\xc3\xcf\x7d\x5b\x20\x07\x7f\x3e\x67\xd8\xeb\xa5\xb3\xf7\x14\xa2\x0a\xe7\x32\xbb\x12\x45\x95\x30\xb8\x8e\x02\x4b\xe6\x75\x49\xd8\xc4\xe6\xc0\xcb\xc4\x05\x60\x1e\xb9\xc4\x84\xdc\x0f\xe1\x9e\x73\x13\x6d\xc0\xd9\xd9\xe0\x18\x3d\x8f\x82\x5e\x7c\x3c\x92\x77\x76\x0f\xb0\x91\xdd\x83\x3b\x8c\x9c\xd7\xa0\xb8\x88\x4b\xb8\x42\x15\x7b\xe9\x1f\x07\xa9\xac\x08\xb7\x01\x0a\xa2\x8b\x42\xda\x86\x90\x13\x16\x40\xb6\x51\xa3\xe5\xa9\xde\x16\x8f\x14\xc8\x7c\x9c\xf8\x87\xf8\xeb\xb8\x46\xd7\x45\x6d\xc1\xd8\xd5\x25\x61\xcf\xa9\x7a\x2c\x39\xa1\x9c\x4f\x7c\x6d\x33\xd5\x76\x0b\x65\x0a\xb9\x96\x00\x4f\x6a\x23\x1a\x50\xe5\xfe\xc9\x4b\x66\x73\x78\xeb\x70\x6d\x29\x2e\x99\x77\x9e\x09\x8b\x2f\xe7\x9d\x65\x42\xf3\x74\x3c\xa0\xed\x15\x63\xcf\xbb\xdc\x47\x27\x6b\x74\x71\xbd\xf2\xe5\x10\x55\x51\x73\x41\x4b\x35\x32\x5e\xe6\x5d\x20\xea\x4c\x51\x14\xc5\x85\xc1\xa2\xd1\x05\xfd\x95\x78\x54\x38\xd5\x39\x2f\xd9\xc9\x4f\xbf\xf9\xce\x78\x09\xbb\xa5\xba\xb4\x97\x3c\xd2\x32\x0f\x5c\xdd\xc2\x66\x20\x8f\xa3\x39\xa7\x2d\x33\x77\xf1\x15\x9e\xe4\x4f\xd0\xfb\xc8\x79\x0d\x7d\x79\x49\xa9\x0d\xa2\x31\xc4\xaa\x2f\x47\x88\x14\x3c\xa7\x5f\x7c\xf3\x11\x0e\xbb\xdf\xad\x1d\xe5\xa6\x4f\x4a\x9c\xc4\xed\xc8\xae\xbc\xd3\xb8\x73\x8b\xe8\x85\x88\xee\x91\xd4\x2e\x95\xfb\x7e\x43\x0f\x67\xcf\xb5\x37\x3a\x38\x45\xc4\x30\xde\xf6\x5d\x72\xbf\x11\x7d\xb1\x8d\xde\x08\x15\x60\x0c\x98\xc4\x36\x52\x51\x78\xdb\x43\xf5\xe0\x25\x0c\x1b\x11\x53\xdb\xea\x5d\x46\xef\xf2\x98\x22\xf3\x48\xfe\x38\x5c\x24\xc5\x22\x09\x52\xca\xba\x40\x8a\x05\x12\x94\xa5\x84\x57\x1e\x10\x76\xac\x43\x4d\x13\xf9\x06\xd6\x04\x83\x9e\x15\xfb\xae\x57\x15\xad\xcd\x48\xe1\xc4\x94\x12\x8f\x4b\xd3\x63\x4f\x0e\xea\xc1\x62\xe6\x83\x58\x3c\x2c\xac\xb5\xca\x62\x1f\xa5\x2e\x4b\x9c\xfd\x08\xd5\x8a\x8e\xf8\x14\x21\x3a\xde\xc0\x44\xc3\xf5\xec\x16\x72\xa1\x32\x3b\x06\x85\x89\x7c\x8d\xca\x94\x38\x81\xb6\xdf\xc2\xdc\xeb\x50\xc8\x5e\x0b\x51\x4f\x00\x2b\xb2\x38\x17\x93\x49\x6c\xc9\x63\x43\xaa\x2f\x0f\x51\x81\xe3\x44\x8c\x1e\x76\xc4\x53\x5f\x62\x77\x14\x3f\xc6\x85\x3d\x2d\xbf\x8b\xeb\x06\xfe\x5d\xec\xa8\x60\xb0\x58\x1a\x83\x7e\x9e\xd4\x5c\x5f\xe8\x9c\xd6\x68\x9f\xe4\xdb\x3c\x67\xda\x93\xce\x3a\xe0\x48\x8b\x4e\xb8\x18\x28\x69\x6a\x28\xe2\x95\x25\x3a\x09\xcd\x66\xb6\x22\xdf\x18\x39\x04\xf3\x31\xb2\xbc\xc6\x8f\x64\x26\xcc\x5b\xfd\x9d\x5f\x70\x9b\x6e\xef\x60\x36\xec\x3d\x47\xfc\xf5\x05\x91\xd9\x64\x39\x4d\x06\xa9\xae\x78\xeb\xcb\x0b\x3c\x0b\xcf\xe8\x17\xcf\xc2\xb7\x35\x35\x05\x18\x22\x3d\xd0\xda\xd4\x87\x41\x41\x5d\x84\x23\x58\x72\xf4\xc2\x84\x34\x3d\x00\x11\xf3\xe5\x2b\xac\xf6\x16\xfd\x62\xb5\x4f\x4a\xd5\x9a\xee\xbd\x0f\x1c\x76\x08\xc2\xdd\x82\xc2\xef\x6f\x34\x96\x40\x8d\xe0\x1b\xca\xfd\x0a\x36\xff\x77\x95\x26\x8a\x0a\x1a\x68\x6f\xb5\x13\x60\x2c\xa1\x44\xb2\x37\x08\x43\x90\x62\x64\xa1\x3a\x75\x8b\x6e\xb0\x28\x97\x3d\x14\x8b\x62\xbc\xa1\x3a\x17\xf0\x5d\x67\x71\x11\xed\xbc\xbd\x2d\xa8\x75\xcb\x35\x02\x1c\x19\x08\x32\x79\x66\x0b\x35\x91\xa5\x53\xc7\x74\xa8\x57\x86\x06\x0f\x17\xce\x38\x2a\x64\x44\x0a\x27\xd7\xc9\x88\xdc\x2e\xec\x0b\x34\xf2\xa5\x08\x91\x6d\x14\x71\xa7\xf2\x30\x72\x3e\xf9\x40\x84\x53\xea\xa5\x4f\x60\x2e\x4c\xe5\x3a\x10\x6a\x81\xc0\x2f\x31\x3d\x84\x01\x40\x42\x57\xf8\xd7\xb7\x41\x91\x27\x55\x88\x6c\x6e\x09\x6d\xcd\x5c\x91\xd6\x16\xa5\x0c\x28\x34\x18\x57\x86\x59\x0a\xf3\x54\xa7\xd3\x0a\x27\x80\xf4\x8d\x84\xff\x59\x11\xa4\x8d\xea\x4f\x37\x40\x83\x67\xa3\x77\x44\x9a\x21\x3e\x3b\x31\x4a\xbb\xa9\xe5\x70\xd1\x33\x2e\x1f\xaf\x50\x23\xdf\x15\xbd\x69\xa3\xe9\x2e\x79\x6d\x33\xfe\xab\xaa\x8d\xd3\xce\x0e\xaa\x14\xe3\x84\x0c\x53\xf9\x22\x72\x86\x3c\xcb\x23\x7a\x18\xf1\x2c\x0f\x6a\x96\xbc\x4e\xad\x48\x19\xe7\xec\x2c\xe7\xee\x22\xd9\x88\x0c\x35\x1d\xc9\x99\x1f\x53\xb5\x7a\x63\xb5\x95\x69\x18\x6d\x19\x52\x6c\x76\xc5\x11\x2c\xbc\x7d\x4f\x1b\xe2\x19\xc1\xf9\x6b\x20\xb1\x0e\x99\x12\x80\x8b\x51\xf4\x67\xac\xd1\x0b\x82\x9a\x7a\xee\x15\x94\xda\x07\x30\xd3\x4f\x4b\x91\x17\x26\xf2\x91\x06\xa1\x8f\x58\x01\x23\x20\x6b\x3a\xe8\xcc\x69\xcd\xc0\x83\x5c\xf9\x86\xfa\xed\x91\x06\xdc\x34\x57\x78\x05\xfb\xf6\x90\xbd\xe0\x91\x5f\x13\x6c\x0a\x7e\xc5\x0b\xb4\x55\x30\xdc\x21\x57\x1c\xcf\x1a\xd3\x64\x73\xda\xa8\x8e\x67\x8f\x0a\xb5\x5a\x32\x3d\x2a\x40\xa9\x4e\x01\x85\x00\x14\x87\x12\xaf\x5c\xb1\x3f\xfd\x4c\xaf\xe3\x02\xb5\x91\x5f\xe0\x8a\x83\xda\xbe\xd9\x19\xd5\x8e\x5c\x4f\xe5\x01\x02\xcd\x73\xfa\xc5\x23\x7c\x96\xca\xed\xc8\x79\xe4\x8a\x35\x4a\x7c\x72\xc5\xd6\xf4\x36\x69\x19\x56\xcb\x96\x6f\x06\xb0\x6c\x43\xc9\x02\x2a\x37\x53\xfd\xd2\xd6\xdb\x7c\x76\xd5\x61\x64\x15\xf0\x9e\x83\x50\x56\x6b\x98\xa1\xd3\x3d\xff\x1a\xd9\x28\x2a\xe4\xec\x8b\x54\x5e\xd4\x76\xa1\xce\x39\x26\x71\xa4\xae\xc4\x66\x2a\x7d\xe7\xce\xf9\x1d\x77\x32\x49\x7d\x74\x43\x09\x64\xab\x5b\x77\x25\x17\x54\x6a\xaf\x3c\xa0\x41\x52\x99\x15\xb1\x16\xe5\x23\xa3\xe0\x50\xb0\xa8\x10\x89\x97\x85\xa2\x2f\xe0\xb6\x40\xda\x56\xb9\x15\x24\x8d\x00\xa4\xda\x9d\x3c\x9a\x57\x84\x2e\x4d\x51\xf3\xc5\x67\xf5\x56\x8f\x5c\x19\x5e\xc1\x8f\xd8\x48\x65\xaf\x0a\x58\x4c\xb9\x63\xa3\xe8\xfd\x4a\x69\x29\xb8\xe2\x55\x3a\xe5\xf6\x42\x13\xa4\x12\xca\x1d\x78\xda\xfb\x53\x1f\x40\xc0\x46\x6a\x84\x84\x19\x2d\xf5\xa3\x54\xee\x33\xde\xfb\x89\x52\x1b\x88\x01\xa7\xf2\x3c\x72\x56\x01\x2e\xad\x52\xea\x39\xa4\x9e\xa7\xf2\x8c\xf3\x7d\xa4\x14\xe6\x7b\x93\xca\x7e\x1d\x52\x9b\x83\xd7\x9b\x7b\x36\x2e\x6a\x2a\x4e\x26\x75\xe6\x26\xca\x3e\xa1\x4b\x5e\x13\x3d\xf6\x1c\xd8\xf7\x59\x41\xf7\xca\x8b\x12\xf1\x38\x95\x6b\x7c\x1a\x1e\x52\x0a\xb0\x34\x9a\xdc\xc7\xd0\xd9\xef\x6f\x02\x62\x39\x30\x62\x9d\xb5\x18\xba\xd4\x50\xc3\x4b\x09\x0b\x81\x2a\x9f\xc7\x66\x7d\xc9\x6f\x27\xe0\x1a\xec\xc0\x11\x4f\x11\x83\xaa\xc4\x86\xcd\x77\x4d\x76\x72\xc0\x59\x58\xf2\xdc\x56\x5d\x3f\x5f\xe1\xf2\x9c\x4c\x3f\xc3\x5a\x07\xf1\xf2\xaa\xd6\xd4\x04\x5a\xed\x52\x33\xa5\x2e\xb8\x1e\xf5\xd5\x9c\xf5\x77\xa9\x3c\x9a\xba\xfd\x10\x14\x67\xf1\xf3\xf8\x4c\x6b\x48\x89\xac\x89\x81\x63\xa7\x2a\x50\x05\x46\x81\xca\xa3\x9d\xfa\x76\x56\xed\x54\x57\x63\x91\xa5\xeb\xa5\x86\xa0\xec\xb3\x54\x6e\xe1\x1a\x7e\x4b\xbf\xe8\xbc\xea\xeb\x79\xb9\xef\x3b\x8f\xb3\x66\x63\xe9\x6b\x76\xe2\x19\xcb\xfa\xba\xeb\x1d\x2b\x02\x8a\xed\x71\x8c\xf0\x26\xe9\x79\xfa\xc4\xd5\x66\xed\x1f\x00\x58\x9f\x72\x41\x5c\xfb\x2b\xaf\x4d\x18\x26\x1d\xf5\x0f\xd7\x8f\x62\x7f\xda\x28\x6e\x5d\x5f\x76\x4e\xe9\x17\xdc\x64\x5a\xb1\xca\x27\x35\x9b\x02\x19\x03\x46\xd6\xa1\x8f\x78\x60\xb1\xb1\xd4\xc7\x33\x15\xfe\x0f\x2f\xfb\x0d\x74\x23\x70\x85\x58\xf4\xf4\x5d\x66\x53\xdc\x1a\x89\x8f\x4c\x68\x7a\x40\xa9\x3f\xb7\x28\x5e\x92\x5c\xf4\xbb\x54\x1e\x47\xce\x18\x57\x62\x8c\xa9\x1e\x91\xdc\x06\xcf\xb6\x49\x77\x8b\xf1\x6c\x69\x5d\xa0\x4e\x7d\x64\x47\x3e\xb4\x35\x32\x2c\xc8\x23\x2f\xc4\xfb\x19\xa5\xde\x4f\x29\xf5\x5e\x3c\xb3\x85\x6c\x8d\x7e\x30\x0c\xb2\xa0\xb1\x27\xbf\xcd\x0a\x5f\x10\x61\x92\x1f\x4a\xef\x8e\x00\x71\xbe\x55\x7a\x07\xf4\xb6\x7c\x92\x89\xf7\xf6\x3b\x84\xcc\xf2\xbb\x4c\x68\xf3\x4e\xf9\x0c\x09\x24\x7f\x90\x05\x89\x0c\x43\x4c\x26\x17\x32\xa6\x04\x31\x35\xe5\x46\x8a\xe9\x4c\xa2\x17\xb6\xd6\x41\x00\x58\x51\x20\x7d\xfc\x7e\x10\x46\x7d\xd9\x4f\x55\x6a\x15\xb6\xfc\xa9\x7e\x78\x16\x5c\xc8\x63\x7c\xd0\xf1\x05\xe4\x20\x16\x01\xcb\x1c\xe5\x6a\x42\xc9\x71\xf4\x49\xa6\x94\x8c\x8f\x47\x7e\x2f\x93\x63\x7e\x60\x22\x1c\x48\x70\x7a\x1a\x47\xd9\xc3\x0b\x19\x50\x5d\xc4\xbf\x92\xcf\xb1\xed\xde\x38\x81\x6e\x1e\xa6\x3a\x49\xfe\xf9\xe5\x05\x3e\xf7\x83\x03\x28\xd5\x03\xb0\x19\x8a\x5c\x16\x22\x5f\xf1\xb7\x01\x0c\x73\x9f\x93\x43\xff\x42\x1e\x50\x32\x44\x4e\x7c\x80\x65\xde\xf9\xf8\x9c\xc4\x23\xd9\x4b\x54\x8a\xab\x1e\x16\x1e\xdf\xa1\x5e\x9d\x1c\xe9\x77\xfc\x38\xc0\xc7\x41\x08\xf3\x70\xa4\x52\x38\xa7\x6f\x29\x3d\xf4\xb3\x2c\x88\xe4\xa9\xf5\xf0\x28\x08\x46\xf2\x98\x5f\xc4\x67\x72\x3d\x55\x29\x6e\xef\x9c\x1e\xe3\x64\x1d\xd6\x48\x86\xd6\x03\x7f\x8e\xd5\x9b\x8d\x48\xbe\x34\x49\xfe\xb4\xaa\x9e\x37\xcf\x22\xf9\x3c\x4f\xf3\xc7\x8f\xf4\x42\x9d\x93\x54\x7e\xc4\x29\x3a\x4c\xe2\xf1\x08\x26\xd9\xc7\x6f\xa4\x85\x00\x0f\x29\x3f\x84\x59\xe8\x0f\xe5\x45\x42\x0f\x19\xfa\xe6\xa1\x92\x72\x9f\xdf\x9c\x06\x49\x26\x1f\x86\x9c\x8e\x3f\x05\x72\x8c\xc5\x90\xb3\x2c\xdf\xe8\xd4\x06\x7a\x19\x86\xf4\xb1\x3f\x92\x1f\x12\x4e\x3c\xc3\x1c\x8f\x53\x7e\x78\x8b\x38\x4d\x2a\x1f\xf2\x23\x40\x0f\x78\x38\x8e\xf3\x07\x2d\xbf\x90\x87\xf4\x32\x38\x8e\xc3\xef\xa1\x25\xaa\x33\x48\x0e\x03\xf9\x94\x4a\x06\xd9\x51\xdc\x97\xef\xf3\xf4\xe6\x40\x7e\x43\x4f\xe1\x39\xec\xba\x0b\x2c\x1c\x05\x87\xb8\x85\x7a\x58\x36\x3e\x0e\x33\xf9\x3d\x66\x88\x71\xe5\x87\xf8\x6e\xe4\x87\x40\xa6\x7e\xcf\xc9\x84\xc6\x7e\x96\xe6\x0f\x3c\x87\x6b\xe6\x0d\x4d\x45\x8f\x1e\x43\xd8\xe3\x27\x94\x1a\x8e\x21\x79\x8b\xc2\xc1\xe9\x8e\xaf\xc7\xd6\x13\x74\xeb\x9c\x9e\xf1\x92\x38\x4f\x54\x6a\x35\x93\xdf\xe2\xde\x4b\xfc\x08\x46\x74\x86\x19\x60\xbb\x27\x87\x72\x2b\xa5\x24\x72\x0e\xe5\x93\x84\xd2\xc7\xf1\x29\x64\xe1\x74\x0a\xfd\xd1\xa9\x57\x7e\xe2\x1f\x03\x74\x14\x7c\xf2\xdf\x51\xe2\x68\x3c\x18\xc0\xe6\xfc\x06\x33\x11\x4c\x97\x5b\x89\xe2\x88\xe0\xc1\x0a\x4d\x1a\x0f\xf0\x20\x35\x8f\x9b\x09\x06\x23\x8b\xe8\xfb\x08\xba\xd2\x97\x03\x4c\x63\x30\x0c\xb9\x9d\xa8\x14\x4f\xc8\x8b\xc2\x23\x1f\x86\x4d\xfd\x8e\x1f\x5f\xf3\xe3\x48\x3e\xa7\xc4\x11\x80\xa3\x0c\x5e\x1f\x85\xfc\x34\x96\x1f\xe9\x7d\x88\x3c\xed\x35\x1c\x7c\x16\x93\x70\x43\xbe\xa4\x1c\xf1\xab\x21\x40\x0e\xe6\x9f\xca\x55\x7a\x05\x13\x95\xc2\xce\x3e\x96\x6f\xf1\x71\x1c\xe1\x52\x3c\xf1\x39\x79\x22\x37\x12\x4a\x7d\x1f\x8e\xe4\x2b\x93\x7c\x17\x02\x85\xfa\x08\x1f\x4f\x79\xcb\x3d\x0b\x4d\x1a\x76\xe9\xb7\xf8\x74\x76\x04\x90\x40\x26\x94\x84\xec\xf1\x38\x93\xef\xb1\x56\xd4\x51\x90\x7d\x7c\x7d\x0e\x90\xfa\x13\x56\x82\x95\x7f\xe3\x73\x42\x75\xed\xa5\x7a\x4f\x2d\x7d\x87\xdf\x10\xf8\xd1\xf9\xa6\x03\xdd\x8b\x87\x43\xcc\xf7\x41\xc3\xbd\x38\x0d\xf8\x4b\x60\xce\x79\x50\x3c\xe4\x01\x8a\xda\xfa\x0c\x85\xd1\x39\x0c\xec\xdf\x80\xa1\x29\xef\x72\x75\x88\x63\xab\x03\x69\x40\x8d\xbc\xe5\x39\x0f\x87\xbc\x43\x70\x5e\xc6\x01\xce\xcc\x45\x0c\xd4\x63\x40\x4a\x0d\xfd\xbe\xdc\x8e\x09\xbe\x23\x8f\x1e\x76\x18\x03\xed\xe3\x60\x88\x88\x80\x7c\xc7\x8f\xa3\x30\xf3\x87\x78\xe8\x9e\x10\xec\x45\x9f\xd4\xf2\xd4\x24\x19\x90\x31\xb0\x3d\x00\x60\x2c\xdf\x63\x1a\x3a\x9d\xd2\x34\x7c\x43\x4f\xc4\xef\x97\xdf\xe5\x69\x96\x10\xcb\x0c\x5b\x47\xaf\x5f\x17\xf2\x1d\x43\x4d\x18\x6c\x94\xaa\x14\xab\x55\xbd\xf5\xd5\x23\x5e\x2b\x8f\xf4\xb7\xe7\x3e\xec\xfd\xc4\x7e\xe2\xdc\xcf\x7c\xeb\x15\x96\xf8\xa4\xf3\xbc\xa3\xb5\x7d\xc6\xcd\x24\x50\xba\x8f\x49\xbc\x4c\xdf\x60\xbf\xf0\x06\x7d\x4c\xb0\xac\x1f\x44\x70\xb8\x2f\xe4\x69\x4c\x90\xad\x37\x1c\xf7\x61\xb7\x7c\x9b\x08\x13\xe6\x46\x1e\xf2\xc3\x16\x1d\xd7\x0f\x54\x0a\xd5\x4d\x58\x30\x24\x0f\xf5\x0b\xdc\xc2\xdb\xb4\x74\xe9\x43\xb6\x69\x90\x17\xfc\x0d\xc5\xec\x72\x9f\xd3\xca\x90\x58\x1e\xa8\x47\x58\x09\x00\x1a\xea\xe1\x64\x0c\x50\xe8\x5c\x3d\xa0\xe8\x5c\x9e\xf1\x03\xcb\xdf\xe4\x0b\xae\x5e\x4b\xe8\xe5\x26\x3f\xbf\x40\xe0\x29\xb7\x38\xeb\x4b\xff\xa5\xdc\xd6\xc9\x2c\x3c\x45\xd1\x28\x3f\x21\x10\xda\xd4\x69\xa4\x73\xe5\x6b\x7e\x52\x3b\x7a\x8d\x9f\xec\xf3\xf7\x9a\x1b\x50\x0b\xb8\xc1\x19\x58\x36\x2e\x5f\xf1\x13\x52\xd9\x7d\x1e\xfd\x23\x7e\xf3\x46\x5b\xa0\xc8\x4f\x21\x5d\x0c\x07\xfe\x01\x6d\xb1\xb7\x58\x1b\xaa\xb8\xc9\x83\x44\xa5\x94\xb2\x9b\x5c\xe7\xdb\xe2\x5c\x7e\xc7\x60\x1c\x48\xdd\x31\x02\xf1\x78\x2d\x8e\x06\x00\xca\x32\xb9\x4f\x40\x3d\x86\xeb\xfa\x80\x53\x67\xf2\x88\xa1\x73\x5f\x06\x31\x27\x9e\x07\x83\x4c\x3e\x53\x6f\xf9\x60\x7d\xab\x20\x38\x49\x2b\x65\x14\x33\xdc\x45\x89\xd7\xad\x90\x60\x69\x7f\x8c\x37\x42\x6a\xd2\x5c\x6c\xc4\x2f\x46\x80\x86\xc8\x84\x21\x74\x0a\xb8\x85\x3c\xa1\x42\xe3\x68\x23\x82\x8e\x65\x70\x60\xe5\x1a\x9e\x42\x3c\x30\xdf\xd1\x79\x8c\x00\x0e\xd2\x60\x3f\x30\x7c\x3d\x06\xca\x59\x03\xde\x40\x6d\xf2\x0f\xbe\x79\x91\xef\xe5\x5b\xf4\x12\x03\x0c\x51\xf1\x5b\xa9\x7e\xe4\xa3\x15\x62\x27\xd2\xf1\xb1\x7c\x41\x20\x53\x49\xd9\x64\x4c\x4f\x49\x78\x0c\xf4\x86\x4a\xd1\x24\xa4\xfa\x89\x87\x33\xe6\x47\xd8\x37\xb2\x17\x13\x80\x50\xa7\x74\x18\x1b\x70\xb1\xd1\x97\x5b\xf8\x74\x16\x27\xc8\x9a\x23\x50\x01\x3b\x86\x8e\xaa\x1f\x5d\xf0\x30\xd0\x27\x32\x6c\x0f\x75\x42\xfa\x80\xb3\xc2\xd2\xf0\x19\x8e\x87\xfd\x21\x4f\x24\x26\x13\x9e\xc2\x23\xbc\x4d\xfa\x49\x7e\xb6\xf4\xd1\xa2\xed\x05\xb9\x09\x40\x55\x24\x16\x79\xd8\x88\x62\xa8\x58\x92\x59\x58\xd8\x3b\x59\xaf\x39\x14\xe0\x81\x58\x57\x19\xca\x20\xd0\x48\x08\xe6\xca\x87\x29\x0a\xe4\x7b\x75\x3b\x6b\x34\x99\xdf\xd6\xf0\x6d\x8a\x0a\x6c\xda\x11\x6a\xd6\xad\x71\x63\x98\x93\x21\xef\x13\x32\x9c\xbb\x72\xbd\xf7\x49\xc1\x33\xa4\x7b\x05\xcd\xbe\x5d\xdf\xda\xde\xd8\x84\xe3\x28\x82\xc0\xd9\x69\x20\xb6\xdc\x10\x0d\x85\x34\x43\x8a\xd0\x59\xfd\xcb\x61\xa7\x44\x43\xe1\x1f\x79\x8a\x3f\xec\x15\x38\xce\xc1\x4e\xb6\x57\x0c\x7c\x8e\x2c\x7b\x6c\xc4\xe0\xa8\x50\x01\xa3\xa5\x90\x00\xcc\x0b\xfe\x9a\x2b\xba\x50\x59\x6e\x8a\x12\xcc\xcb\xef\x91\xf9\x29\xe5\xc3\x8e\x45\xb7\x40\x53\x36\x21\x6c\xc2\x48\xaa\x09\xe3\x46\xc8\xf1\xa2\x2f\xe3\x85\x85\xa4\x6b\x39\x8a\x64\x27\x90\x2a\xb2\x01\xc6\xd9\x84\x02\xfa\x66\x4b\x71\x96\x9d\xd2\x1b\xf2\x2a\xaa\xf5\xb1\x94\xd2\x5f\x1f\x4a\x7b\xf3\x6d\x41\x14\x02\x7a\x25\x25\x3f\x69\xf0\xab\x8a\x79\x14\xeb\x8c\x62\x54\x0e\x43\xc0\xf4\x30\x60\x37\x76\xdc\xc3\x49\xf1\x0b\x5d\x44\x19\x5c\x24\xfc\x2b\x7b\xb6\xd4\xcc\x4c\x99\x94\xac\xd9\xe0\x39\x9b\x3a\x25\xb9\x92\x63\x65\x42\x48\x33\x74\x3e\xe0\x3d\x64\x56\xc6\x29\x4e\x0b\xfb\x21\xc8\x15\xf2\x4e\x7d\xe7\x9b\x98\x9c\xb1\x91\xab\x9a\xc4\x0d\xba\x21\x54\x8b\x7d\x5c\xc3\x19\x80\x51\x1c\xfb\x4e\xe9\x15\xb2\x22\x0e\x12\x7a\x6b\xcd\xa6\xdb\xa2\x09\x91\xec\x82\x5e\xad\x1b\xe6\x39\x0d\x83\x33\x9e\x7f\xeb\x89\xe6\x5e\x99\xd9\x5e\x22\x48\xf3\x22\x9e\xc7\xac\x49\xd9\xfa\x61\xb2\xbf\xff\x60\xa9\xdb\x50\x11\xd2\x50\x58\x69\x79\x74\x15\x85\x09\x6a\xaa\x5c\xb5\xda\xa3\x34\x7c\xe3\x00\x14\x66\x13\xbe\x59\x0e\x41\x6b\x6b\x52\x3b\x57\xd6\xb2\x03\x4a\x15\x46\x7b\xf4\xd5\xaa\x52\x2f\x38\x21\x03\xb0\xe2\x78\xf7\x4c\x59\x71\xde\x0d\x4d\x27\xb0\x07\x3a\x75\xf5\x0b\x5d\xc0\x86\xdb\x26\x38\x39\x06\x93\xd7\xed\x2a\xf2\x0a\x5a\x46\xec\x7d\x5a\xcb\xb4\x1d\xa9\x65\x68\x94\x1b\xff\xac\x96\x4d\x73\x44\x99\x40\x63\x84\xe2\x4e\x3b\xee\x5d\x0d\x20\x3c\x06\x10\x70\xf4\xbb\x1f\x03\x6f\x3d\x9e\x7e\xfa\x2b\x6d\xb2\xf0\xf9\xaa\xcc\xe8\x60\x2a\xbf\xbe\xab\x8a\x5a\x76\x4e\xe3\xe2\x4a\x6b\xca\xa7\x7e\x81\xe5\x47\xe6\x6f\xb5\x95\xa7\x59\x55\x49\x75\x73\xcd\x67\x28\x2a\x2b\x55\xcd\xd4\x50\x89\xab\x65\x2c\xad\x97\x3c\xd2\xed\xd4\x8e\x06\xc9\x51\x2f\x37\xbb\xb4\x92\x75\x95\x6e\xb3\x21\x7a\x9c\x45\x0c\x9e\xcc\xec\x78\x7d\xae\x71\x16\x04\x7a\xc5\xdf\x52\x1c\x40\xd6\xb2\x45\xd7\x66\x51\xce\x4a\x70\x16\x03\xd7\x8b\xa8\x26\x52\xa0\x45\x19\x75\xa1\x9b\x9a\x12\x9a\x32\x71\xd4\xd2\x12\x0c\x0d\x2e\x45\xab\x58\xc1\xc3\xa4\x06\x46\x24\xab\x42\x2b\x48\x2d\x67\xba\xf3\x3b\xa7\xeb\xf1\xac\x4d\x60\xb9\x27\x3c\xdb\xee\x84\xce\xd5\x2d\xa5\x89\x14\xa1\x1a\x80\xca\x09\x07\x65\x82\xc7\xc4\xcd\x3f\xda\x3a\x2f\x28\x6a\xad\x68\x81\xe7\xfa\x52\x7e\x49\x23\x1c\x6d\xc6\xcb\x8e\x7a\xc7\x72\x7e\x7e\x8a\xc7\x61\xd1\x93\x85\xe8\xc8\xef\xc5\x50\x92\xff\xab\x91\xec\x91\x1f\xea\xd4\xed\x8c\xc8\x32\xb8\x86\x3f\x3d\x5c\x58\x68\xcf\xcb\x61\xee\xbc\xb8\x27\x47\xc6\xed\xf9\x80\x02\xde\x8e\x71\x6e\x0a\xe1\xc4\x06\x5d\xe5\x6b\x0b\x43\xd8\xea\xb8\x00\x85\x2b\x9d\x8a\x1f\x15\x4e\x03\x4f\x2d\x3a\xe4\x2e\xab\x94\xa3\xf3\x41\xa1\xa3\xec\xa1\x11\x00\x71\xff\x55\x4c\x53\x20\xb0\xbb\xa9\x67\xdd\x93\xe2\xd4\xf8\x6e\xeb\xa3\xc2\x8d\x0a\x76\xe6\x8c\x27\x93\xd3\x62\xac\x1f\x2a\x7f\x2c\x0b\x6f\x01\x8c\x17\x9e\x09\x90\x1f\xdb\x2a\xf3\x40\x72\x93\xce\x3c\x06\x73\xd5\xda\xf2\x41\x0e\xbc\xd9\x9b\xf3\x69\x1e\x4e\x77\x2e\xc7\x7a\x8e\xe0\x78\x6b\xb0\xc2\xce\xc5\x01\xae\xa0\x49\x1a\x62\x28\x74\x7b\x62\x3b\x04\xd8\x08\x21\x81\x54\x7a\x14\x0e\x30\x17\xa2\xb8\xf8\x43\xca\x9e\x2a\x81\x2f\xc6\x11\xe7\xd8\xab\x48\xd1\x23\xe9\xd0\xee\x53\x75\x4d\xa8\x84\xd9\x80\x99\xdb\x7d\x18\x7b\x6f\x62\xbc\x31\x00\x5a\x51\x4e\x6c\x7c\x82\x0d\x4d\x54\xad\x76\x6e\x00\xe5\x23\x80\x6e\x38\x8e\x86\x50\x47\x00\xbb\x3e\x81\x8e\x4f\x4c\x1b\xa5\x52\x85\x4d\x9e\x55\x36\xb9\x15\xaa\xc2\xe8\x96\xc3\x3e\x2a\xee\xf6\x6e\x64\xb9\x41\xcb\xbd\x85\xf3\xc5\x0f\xd8\x6a\x1d\x2e\x19\x99\xcd\x82\x08\x25\xce\xf9\x4f\x39\xe6\x09\x6b\x29\xc5\xa8\xa5\x14\x22\x72\x4c\xbf\x85\xab\x1d\x33\xc0\xd5\x4e\x1b\x23\x51\x2d\xf9\x3b\x9b\x11\xc9\xab\xc4\xa6\x4b\x35\x40\x11\xce\xd8\xe0\xf3\x0a\x68\x24\x15\x20\x4d\xb7\xbd\x22\xb8\x27\x26\x41\x90\x95\x80\x39\x5d\xbd\x32\x29\xbe\xa6\xa9\x90\x6f\xb3\x02\x52\xce\xbc\xe2\x37\x45\x4c\x1d\x2e\x11\x44\x5d\x1e\x17\xdf\xc2\x92\x01\x19\xf7\xb0\xf8\x52\xb7\xf5\xb4\xf8\x5a\x6b\x71\xcb\xef\x4b\xd9\xc7\xe8\xfb\xd4\xce\xf7\xcd\x36\x60\xe9\x41\xb9\x9b\x40\x96\x56\xde\xc9\x93\x72\x2f\x99\xcb\x63\xbf\x03\xe8\x5a\xc8\x43\x34\x90\xfd\x82\x60\x6b\x91\x2c\x09\x2a\xb5\x30\xa8\x2e\x0e\x08\x19\x3c\xc5\x81\x63\x3d\x24\x0e\xdc\x12\xdb\xb2\x71\xb7\xf5\x75\x6b\xa9\x21\x5e\xc8\xb6\xd8\x94\xcb\xe2\xb5\xbc\x27\x36\xe4\xd7\xe2\x95\x6c\x7f\x25\x1e\xc9\xbb\xcb\xe2\x93\xfc\xea\x9e\x78\x29\xdb\xcb\x5f\x8b\x55\xb9\xfc\xe5\x57\xe2\xb9\xbc\xbb\x24\x3e\xca\x46\xab\xd5\x6a\x88\x37\xb2\xfd\xe5\x92\x78\x8c\xb9\x1f\xca\x25\xf1\x14\xaa\xf9\x1e\xaa\x39\x91\x0d\xa0\xfe\xa1\x7f\x41\x7f\xce\x37\x92\x97\x86\x78\x87\xa6\xd4\x6c\xa9\xbc\x6f\xd1\x22\xfb\xfb\x0d\xf1\x56\x36\x76\x98\x4d\x35\x67\x38\x25\x7b\x0d\xf1\xcc\x7e\x0d\x17\x1d\xbc\xfa\x36\x7f\xa5\xb8\x26\xf0\xf2\x43\xfe\x12\x79\x27\xf0\xe6\x56\xfe\x86\x18\x23\xf0\xea\x49\xfe\x4a\x33\x44\xe0\xed\xfb\xfc\xed\x0b\x7f\x04\x2f\xbe\xc9\x5f\x30\xd7\x03\xde\x7d\x97\xbf\x63\x46\x07\xbc\xcb\xb2\xfc\x25\xf3\x3b\xe0\x65\x60\xbd\xdc\x0e\x30\x5b\x64\xbf\xa1\xed\x05\x2f\x13\xeb\xa5\xd2\x56\x87\xb7\x61\x56\x1a\x2e\x9b\x01\xc0\x97\xd8\xfa\x42\x1a\xeb\x77\x97\xf5\x7c\xf8\xe5\x4f\x4a\x99\x1d\x3e\xa5\xd6\xa7\x0d\xad\x2d\x0f\xef\xc7\xc5\xf7\xed\xaf\xf4\x87\x5e\xf1\x43\xde\xc8\xd0\xfa\x90\x2b\xde\xc3\x87\x51\xf9\xc3\xda\x10\x08\x66\xc5\xdf\x81\xef\x83\xd2\xf7\xbc\xad\xa3\xd2\x97\xbc\xb1\x7e\x86\x0a\xcf\x68\xaa\xbc\x8b\xc6\xe1\xb7\x3b\x77\x0e\xc5\x29\xbd\x73\xd4\x4b\x17\xcd\xc0\x77\x9b\xf0\xfe\x18\xde\xc3\xdb\x60\xd7\x69\x7d\xd1\xdd\x75\x27\x58\x2e\xdb\x75\x5d\xf8\xba\x1b\x71\xd1\x43\xc8\xb2\x00\x70\x1c\xfa\x35\x19\x66\x93\xc3\x6c\x72\x32\x8e\xb3\xc9\xaf\xef\xde\x9f\xfc\xfa\xfe\x57\x2e\x66\xb9\x80\x2c\x3b\x0b\x0f\x56\x1a\xb7\xff\xda\x1e\x3c\xee\x67\x92\x17\xd4\x39\xd4\xa1\x7a\x5d\x71\x60\x5e\x5e\xe4\x2f\xd7\xa1\xe0\x83\xdf\x2c\x3a\x3b\xbb\xe9\xee\xf6\x5e\xb3\xeb\xfe\x66\x05\xca\x9f\xd3\xdb\xd2\xcb\x33\x7a\x29\x4b\x6f\xd7\x70\x5c\xad\xc9\xee\x0e\x74\x70\xe7\x77\x3b\xbb\x7b\x7b\x5f\x4c\xe0\xde\xbc\xbd\xe7\xc2\x0b\xa7\x3b\xbf\xdb\x76\x77\x7e\xb7\x1b\xed\xee\xee\x4d\x76\x77\x5b\x2e\x8c\xb1\xed\xee\xee\xdd\x11\x5b\x50\xee\x77\xbb\x67\x5f\xdc\xba\x23\xb6\xb1\xf3\xbf\x6b\x61\xd9\x26\x57\xe4\x2c\x76\x77\xfb\x4d\x48\xec\xb6\xe0\xd7\xed\xba\xba\x4a\x55\xe7\x72\xa9\x4e\x17\xde\xec\xe2\xc0\x5f\x60\x55\xad\x2f\x9a\xdd\xdf\xdd\xba\xbc\x72\xdc\x09\xd4\xb9\x7b\x67\x97\x3e\x6d\x9a\xe1\xbf\xc8\x87\xff\x1a\xf3\xef\x8e\x97\xee\x2e\x2d\x2d\xe2\xcf\x57\x83\xdd\xf1\x20\x58\xc6\x07\xf8\xb9\x8b\xe5\x36\x70\x80\xbb\xce\xee\xae\xdb\x85\xa7\x57\xf8\x74\x6b\xf7\xd2\x81\x0e\xec\x5e\xed\x7d\x81\x7d\xdc\x6d\xa9\x07\xf7\x0b\x77\xf7\x0a\x32\x3d\xc2\x4c\x34\xb4\x4f\x38\xca\xa5\x9d\xf3\xf7\x30\xe2\x97\x34\x62\xbd\x63\x5a\xcd\xee\x5a\x2e\x1d\xdd\xdd\x83\xcc\xab\xd4\x99\xf3\x1e\xb4\x7e\xde\xff\x0a\xfe\x7f\x8d\x89\x00\xfe\x0f\x20\x31\x80\x37\x03\x7c\x33\x18\x60\xb7\x9e\xe3\xbe\xb9\xf5\x3b\xf7\x8e\xf8\x88\xc5\x6e\xc3\x74\x24\xbb\xe3\xe5\xa5\xe5\xaf\xe9\xef\x7d\x1e\xf4\x9b\xac\x7a\x99\x37\x76\x56\x17\xbf\xdb\xe5\x76\xa8\x21\x6e\x09\x9b\xc2\xf3\x0f\xdf\xfd\xc5\xef\x77\xb9\x55\x6a\x96\xdb\xa5\x86\x9b\x0d\x8d\x01\xa8\xb9\x04\x5a\x15\xd6\x49\x36\x9a\x59\x33\x68\x36\xdc\x09\x26\x1a\xdd\x46\x93\xfd\x44\xe0\xd7\xc9\xce\xd2\xe2\x7d\x28\x48\x7e\x21\x90\x59\xf5\x18\xba\x30\xf7\xcf\xfc\xb3\xbb\x83\xff\xf7\xcf\x71\x96\x07\x83\x72\xd7\xff\xc9\x3f\xfc\xe1\x9f\xfc\xf9\x3f\xf8\xf1\x87\x1f\x7e\xfc\xe1\xcf\x7e\xfc\xe1\xaf\xff\xf8\xc3\xdf\xf8\xf1\x87\xbf\xf9\xe3\x0f\x7f\xeb\xc7\x1f\xfe\xf6\x8f\x3f\xfc\x9d\x1f\x7f\xf8\xbb\x3f\xfe\xf0\xf7\x7e\xfc\xe1\xef\xff\xf8\xc3\x3f\xfe\xf1\xcf\xfe\xd1\xff\xf7\xc3\x0f\x0d\xf1\x30\x93\x3b\x0d\x3a\x7d\xd0\x8c\x05\x78\xe0\x09\xa1\x29\xfc\x10\x08\x85\x5f\x1b\xf6\xe8\x47\x05\x6f\xf0\xd1\x40\xfa\x86\x01\x37\x9c\x56\xc7\x9e\x1f\xf2\xf2\x68\x2b\x06\x3f\x0c\x66\x21\xc1\xb0\x15\x12\x3c\x3d\x90\x00\x18\x8a\x7f\xd9\x90\x41\x34\xf6\x91\xf9\x65\x59\x37\xc1\xa3\x36\xf3\x82\xa4\x66\x7b\x33\x2b\x8c\x18\xb8\x88\x44\x1a\x5b\x22\x78\x30\x36\x66\x90\xce\x01\x99\x7e\xb0\x81\x97\x7a\x97\xf7\xdc\x02\x52\xf0\xa4\xa0\x36\x92\xcc\x64\x73\x06\xb8\xe9\x53\x0a\xcb\xf3\x3d\x31\x23\xbf\xcf\x76\x62\x40\x05\xe1\xc7\xe7\x9f\x94\x7f\xc6\xfc\xd3\xe3\x9f\x21\xff\x8c\xf8\x67\xc0\x3f\x47\xf0\x33\xbf\x24\xd0\x8b\x20\x3d\x3f\xa3\xbf\x21\x7f\xfc\x96\xfe\x7e\xa0\xbf\xb7\xe8\xef\x13\xfa\xfb\x9e\xfe\x7e\x43\x7f\xbf\xa3\xbf\x19\x17\x08\xf8\x27\xe2\x9f\x04\xeb\x66\x8d\xb1\x13\xea\xe7\x09\xb5\x72\x42\xad\x9c\x70\x2b\x27\xd4\xca\x09\xb5\x72\xc2\xc3\x38\xe1\x61\x9c\xf0\x30\x4e\x78\x18\x27\x3c\x8c\x13\x6a\xf6\x84\x9a\x3d\xe1\x66\x4f\xb8\xbd\x13\x1e\xe0\x09\x0f\xf0\x84\x07\x78\x62\x06\x78\x42\x23\x38\xa1\x11\x9c\xd0\x08\x4e\xb8\xbb\x27\x85\x7e\xbe\x83\x7e\x6a\xd7\xbc\xe8\x2e\x9c\x5d\xed\x7a\x4b\xc2\x38\xe4\x9d\x6f\x5f\x89\xb7\x90\xab\xf1\xfb\x1f\x00\x77\x5f\x85\x25\xf9\xfd\x9f\xe9\xc4\x5f\xd7\x89\xbf\xa1\x13\x7f\x53\x27\xfe\x96\x4e\xfc\x39\x24\x7c\x4c\xfc\x07\x3a\xf1\x1f\xea\xc4\x7f\xa4\x13\xff\xb1\x4e\xfc\x27\x3a\xf1\x77\x20\xb1\x86\x89\xff\x0c\x12\x3d\x4c\xfc\xcb\x90\x78\x84\x89\xff\x0e\x12\xc8\xb8\xfd\xfd\xdf\x85\xc4\x3a\x26\xfe\x9e\x4e\xfc\x7d\x9d\xf8\xe7\x75\xe2\x3f\x87\x04\xee\xd8\xdf\xff\x17\x3a\xf1\x5f\xea\xc4\x7f\xa5\x13\xff\x02\x24\x36\x30\xf1\x2f\xea\xc4\x3f\xd0\x89\x7f\x49\x27\xfe\x6b\x48\x84\x98\xf8\x6f\x74\xe2\xbf\xd5\x89\x7f\xac\x13\xff\x0a\x24\x5e\x62\xe2\xbf\x87\x04\x1e\xd3\xdf\xff\xab\x90\xd8\xc4\xc4\xbf\xa6\x13\xff\xba\x4e\xfc\x1b\x3a\xf1\x6f\xea\xc4\xbf\xa5\x13\xff\x03\x7a\x31\xc1\xc4\xff\xa8\x13\xff\x93\x4e\xfc\xcf\x3a\xf1\xbf\xe8\xc4\xff\xaa\x13\xff\x36\x24\xde\x60\xe2\x1f\xea\xc4\xbf\xa3\x13\xff\xae\x4e\xfc\x6f\x90\x18\x63\xe2\x7f\xd7\x89\xff\x43\x27\xfe\x4f\x9d\xf8\xf7\x20\xf1\x01\x13\xff\x17\x24\xf0\x2c\xfe\xfe\xff\xd1\x89\xbf\x8d\x6b\x4a\x53\xf6\x9f\xe2\x3a\x51\xea\xdf\x87\xd4\x6b\x04\x33\xbf\xff\xbf\x89\xb4\xc3\xd4\x3f\x82\x54\x9a\x36\xae\xc4\x33\xdc\x37\x0b\xf0\xb4\x00\x27\xbf\x03\x9f\x1e\x60\x7a\x98\x61\x72\x05\x93\x87\x98\xbc\xdd\xb8\x0d\x49\x44\x1b\xf0\xfd\x6d\x7c\x0f\xe8\x03\xa6\xff\x1a\xa5\xef\x7f\xd5\x81\xba\xbe\xa5\xba\xa8\x1e\x78\x09\x1f\xa9\x1e\x0f\xaa\x14\x5c\x8f\x07\x55\x0a\x5d\x8f\x07\x95\x0a\x55\x8f\x07\x75\x0a\x55\x8f\x07\x75\x5e\x89\x0f\x58\x97\xc1\x9c\x3d\x38\x2e\x7c\xf1\x41\xea\x4a\xdc\xc2\x8f\xbb\xbb\x90\x15\xfe\x70\x7f\xb0\x3c\x39\x6f\xc1\x55\xdd\x45\x0e\x1d\x42\x38\xbe\x16\x70\xde\xe8\x57\xbd\xb8\xaf\x5e\xdc\x87\x76\x9e\xa0\xb2\xd0\x8e\xb6\x1a\xc0\xa0\xf0\x40\x9a\x46\x96\x36\x6c\x24\xde\xdb\x59\x02\xc8\x12\x20\x8b\xda\xca\x12\x88\x6f\x50\x95\x68\x61\xe1\x7d\xc1\xfd\xae\x15\x2e\x1e\x95\x2f\x19\xb6\x43\x4a\x7c\x67\x57\x08\x84\xcc\x00\xea\xc4\x1f\xfe\x6b\x32\xe2\x83\xc8\x02\x2b\x2f\x43\x5a\xc8\xcd\x09\xfd\x6b\x4a\xf0\xa3\x08\x02\xf9\x9e\x7a\xd3\x0a\xce\xc9\x30\x4c\x4a\xea\xde\x13\x20\x83\x03\xf9\x4d\x36\x99\x64\xc8\x79\x23\x52\x1b\xfa\x83\x04\xb7\xb1\x1b\x46\x8f\x4c\xdf\x61\x0e\x72\x88\x1f\xc8\x35\xc7\xed\xfc\xea\x57\x35\x2c\x23\x96\x58\xd6\x8c\x97\x3f\xb4\xfc\xe3\xfe\xc2\x42\x9e\xee\xa2\xbd\xf5\xbe\x4c\x02\xc1\xef\x6a\x4c\xf8\x92\xe0\x0a\xcd\xb5\xa9\xe7\xdd\x20\xe8\x3a\xd6\x00\x92\xc0\xa5\xd2\xf0\x99\x7f\x55\x6d\x57\x6e\xee\xee\xdd\xb5\x1f\x6c\xb7\x7e\x46\x6f\x94\x9d\x97\x74\xf9\xc7\xab\xcb\x81\x73\xde\xc5\x3f\xb5\x5f\x79\x96\xba\xfc\x83\xfe\x17\xaf\xc4\x25\x90\xf6\xbf\xf5\x76\xca\x1a\x85\xc6\x5e\xce\x0a\x36\x59\xf5\xb5\xdb\xcd\x3c\xcd\x51\x6d\x34\xbc\xac\x10\xb3\xab\xec\x79\xbb\xba\xaf\xec\x48\x1d\x16\x97\x5a\xd7\xc8\xf1\x5a\x0a\xee\x36\x53\xd6\x36\x54\x91\x5c\x4c\x71\x7f\xb6\x3e\x77\x46\x3e\x55\xb2\xdf\xb4\x25\xba\xb9\x3b\x58\xb1\x7d\x16\xa7\xb6\x01\x5a\xee\x25\xf9\x30\xd7\xe8\x1e\x76\x2f\x98\x4f\x74\x9a\xbb\x48\x66\x8f\xcb\x47\x55\x0f\xc9\xe3\x82\x4b\x96\x44\xb9\x64\x19\xd4\x78\x64\x19\x59\x8e\xee\xc8\x61\x4d\x95\x50\x1e\xd6\x92\xbb\xa3\xa9\x18\xfe\x40\x23\xf8\x23\x83\xdf\x1f\x5d\x83\x72\xf7\x25\x1f\x3d\x8b\xe7\x74\x2a\x75\x63\x75\x16\xf7\xc7\xb2\x5f\xb6\xb7\x3f\x84\x57\xe6\xfb\x85\xee\x03\x1a\xd9\x8f\xf5\x9c\x1d\xbb\x96\xa9\x7d\xb1\xf8\x4f\x35\xb8\xdf\x97\xb1\xc3\x7e\x0d\x1a\x4a\x15\x03\x5e\x1e\xc8\xfb\x4b\x4b\xbf\x6d\xdf\xbf\xbf\xfc\xe5\xbd\xdf\xde\x5b\xba\x7f\xbf\x2d\xd6\xe5\x7e\xad\xe9\x01\x2f\xa1\x6f\x5b\x1e\x58\x8b\xde\xbb\xea\x04\xe6\xec\xae\xf3\x29\xf9\xba\x7a\x4a\x72\x20\x60\xf9\x3d\xd1\xae\xdc\xf6\x0f\x83\x2c\x22\x7d\x8c\x06\xb9\x81\xc8\x0d\xb5\x31\x2a\xad\xf2\xad\x90\xa3\xbc\x68\x84\x14\xdf\xd4\x44\x81\xdc\x47\x5b\x5d\xf4\xff\x24\xa0\xa3\x66\xa4\xde\x7d\x98\xa9\xfb\x7f\x59\xe0\x89\x7f\x2d\x3c\xb1\x81\xc2\x69\xbe\x3f\xc6\xdd\x63\x3e\xd3\x47\x65\xa0\x30\xaa\x02\x85\xb4\x16\x28\x0c\x6b\x80\x42\xaf\x04\x14\xc6\xb5\x10\xa0\x37\x15\x02\x0c\xf5\xe9\xeb\x19\x08\x30\xba\x06\x02\x0c\xaa\x10\xe0\x68\x26\x04\xe8\xcb\x41\x19\x02\x9c\xc2\x2b\x0b\x42\x58\x10\x20\xd5\x13\xd4\xff\xd9\x21\x80\xb5\xfb\x63\x3e\xa0\xed\xa5\xd9\xfb\x0e\xb7\x44\x63\x9c\x06\x73\xb8\xef\x60\xe7\x74\x42\xeb\xcc\xb0\x99\x35\xa2\x12\xa3\x04\xf6\xfe\xf9\xd3\x00\xe5\x77\x40\x3d\x2b\xb1\xd6\x91\x79\x56\x5a\x43\xf5\x5a\xea\x4b\x64\x8b\xa4\xec\xcd\x60\xa7\x19\x73\x19\xc0\x81\x8c\x9f\xd9\x3d\xb2\x17\x80\x13\x84\x26\x74\xcc\xc4\x07\xb0\xd1\xba\x13\x46\x03\x82\x05\xfb\x28\x4e\x1d\x67\x41\xd2\xfa\x98\x36\x50\x3e\x87\x5f\x5b\x77\xc6\x59\x38\x4c\xef\x1c\x84\x91\x9f\x5c\xec\x93\x4a\xc4\x3e\x7b\x3d\xa3\x6c\xc6\xa2\x8d\x22\x0f\x84\x6e\x58\x5a\x25\xc7\xa7\xb8\x29\x3b\xfe\x9e\x0c\xe1\x0f\xcb\xb6\x52\x75\x3a\x64\xc8\xd1\x82\xc3\x7c\xc5\x3b\x89\xa5\xe4\xae\xf6\x08\x2b\x69\x63\xa4\xea\xa4\xc0\x11\xcf\xb5\xdc\x13\x72\xc7\x94\x8e\xd1\xd8\x20\x7f\x8d\xa1\x4d\x85\xaa\x83\x21\x8b\xe9\x95\x55\x91\x68\xa0\xad\x60\x9c\xf9\xc3\xed\x5e\x12\x0f\x87\xe8\x1d\x80\x97\xa1\x21\x2e\xcf\x92\x30\x23\x77\x01\x18\xb3\x2a\x86\x89\x3a\x1c\x27\xfa\x99\x83\xe7\x59\x08\x59\x61\x95\x99\xeb\x53\xbb\xb4\x25\x7f\xb9\xb4\x78\xdd\x25\xaf\x36\xef\x4e\x06\x0b\x87\x92\x93\x9b\x8d\xe3\x51\x98\xc2\x6e\xbf\x20\x4d\xaf\x6d\x54\xea\xfa\xbc\x31\x64\xa5\x41\x68\x97\x4a\x2d\x5e\x7e\xae\x96\x5d\xde\xd5\xf6\x16\xf6\x73\xdc\x8a\x47\x59\xda\x5a\x7b\xbe\xb9\xbd\xbe\xfd\x7a\xff\xe9\xc6\x93\xa7\xeb\x5b\xee\x4f\x1b\xc1\x3a\xea\x31\xfd\x53\xd1\xff\x66\xfb\xe6\x23\x78\x1d\x8f\xb6\x47\x00\x71\x92\x9f\xb2\x8b\xca\x23\x50\x36\x71\x8b\xed\x5c\x53\x20\x98\xba\x57\x82\xcf\xd8\x29\x0f\xe3\x2c\x8b\x8f\xff\x98\x1d\xa5\x6d\x4d\x1d\x9d\x76\xc0\x50\x41\x69\x65\xe6\x19\xd1\x43\x9d\x5e\xc3\xe2\xac\xa9\xc8\x81\x75\x82\x88\xc3\x75\xd0\xcc\x6b\xdf\x13\xd3\x00\xa2\xd7\x5e\x46\x60\xdf\x9e\x09\xec\x4b\x73\xc2\xaa\x7d\xec\xaa\xaf\x3e\x3a\xd9\xb5\x60\xd8\xc0\xd7\x78\x0a\x7c\x8d\x19\xbe\xc6\x08\x5f\xe3\x3d\xed\xc9\xef\xa7\xc0\x57\xff\x2f\x15\x7c\xb5\xf5\x07\xf2\x5b\xf2\x0b\x7a\x66\xd4\x75\x73\xb0\x76\x14\x0e\xfb\x49\x10\xfd\xa9\xe1\x27\xf2\xab\xd9\x95\x96\x93\xdd\x29\xf5\xf8\x4f\x0c\x1a\xa9\x6b\xe8\x02\xec\x0f\xea\xd9\xcf\x0a\xf2\xf4\xca\x7e\x51\xea\xcf\x9f\x0e\xb6\xd9\x73\x75\xec\x9f\x3b\x4b\xc2\xa9\xdd\x67\x8b\x99\x5b\xee\xb4\x5b\x07\x86\x66\x42\x98\xe5\xcf\x44\x27\x4b\x0d\xa2\x37\xc4\xba\xbe\xc9\xe0\xea\x4f\x75\x54\xf3\x00\x7b\x24\x42\x71\xa6\xb6\x32\x17\xc5\xd9\x5c\x88\x8a\xd3\x08\x1e\x83\x7e\xab\xf1\x13\x4f\xc7\xcf\x70\x74\xeb\x3a\x5d\x69\xe2\x67\xeb\xf0\x1f\x7c\x9c\xaf\xeb\x2e\x34\xf0\x07\x75\xf6\x67\x3d\xe1\xf5\x1b\xa2\xd0\xc0\x1f\xd4\xd9\x9f\xfb\xfc\xd7\xf5\xb7\xda\xc6\x94\x2e\x17\x0f\x3f\x9e\xf0\xbb\x37\x62\xe9\x44\xad\xad\xc0\xef\x21\x4f\xd9\x69\x24\x98\x22\x7e\x4e\xce\xe8\x09\x53\x5f\xf1\x9f\xe2\xc2\xdb\x41\xce\xd8\x21\xbc\x42\x83\x98\xf4\x8e\xb6\x83\xdd\x9f\x42\xf1\xa5\xe5\x02\xd4\xc0\xb4\xdc\x63\x99\x28\xcc\x61\x6d\xe8\xa7\xa9\x73\xd9\xe7\xed\xf6\x92\x94\xb9\x36\x54\xa1\x86\x40\x1b\x45\x64\xf8\xa7\xde\xe5\x91\x1f\xf5\x87\x01\x9f\x7a\x2f\x69\xbd\xd2\x5f\xc8\x7a\x14\x32\x06\xc3\xd8\xef\x3f\x44\x23\xa3\x6d\xd4\x0a\xb7\x73\x30\x38\xd3\x79\x56\xfb\x7d\x32\x94\xf4\x87\x3c\xf5\x75\x59\x03\x5e\x87\x9a\x0c\x71\x14\x6c\x0e\x30\xe9\xec\xd4\x94\xb3\x5f\xd1\x04\x6c\x0e\x9c\x6a\x36\x77\xcf\x25\x7b\xa5\x93\x71\x08\x84\xb9\x50\xe6\x2a\x7a\x2b\xd4\xf4\xc7\xce\xad\x67\xf4\x39\x0e\x37\x38\x0c\x23\xde\x4c\x9b\x83\x41\x1a\xd4\x8e\x25\x8e\x36\xac\x22\xd5\xa9\xc3\x39\x09\xa3\xc3\xed\x51\x18\x41\x1f\x1e\xc1\xd0\xd1\x26\xb5\x58\x53\xdc\x0f\x44\x98\xda\xf5\x50\xd4\x52\x2b\x0b\x46\xc8\x11\x68\x2f\xc9\x2b\x04\x10\x0e\xf2\xf9\x69\x96\x3e\x8e\x93\x55\x34\xe6\x7e\x93\x06\x09\x7f\x4b\xeb\x7a\xd9\xc3\x7d\x40\xcb\x6f\x7f\x64\x76\xdb\x95\x40\x80\xc4\x86\xd3\xf8\x2d\xb5\x6f\x0b\xe5\xb7\xa2\xb0\x3d\xac\xcf\x57\xd3\xc7\xc7\x1b\x50\xd9\xba\x39\x8d\x7e\x78\xda\x10\xec\xc3\xad\x34\x65\x85\xea\xaa\xd3\x30\xdf\xbe\xf1\xc0\xdb\x5f\x2e\x5d\xd1\x68\x36\x58\xd5\x9e\x72\xdb\xf5\x5b\x94\x3f\x77\x4f\x37\xb6\xa6\xce\x8f\xa6\x3d\x61\x16\x5a\x85\x5d\x2a\xac\x0f\x3d\x75\x6f\x53\x20\xf8\xfc\x75\xf9\x90\x74\x67\x7c\xf3\xec\xea\x8a\x1b\xf4\xce\xb2\x88\x6a\xaa\x2d\x9f\xab\x9a\xda\x2b\x47\x6f\x7a\x23\x0a\x6f\xba\x0c\x4b\xe3\xf7\x32\x51\xc6\x4e\xbc\x9a\x91\x6b\x0d\xed\xb4\x84\x25\x28\xc6\xa9\xe8\x97\x6f\x63\xaf\xf8\x0e\xae\x3c\x2f\x6b\x55\xef\x41\x27\x68\x62\xec\x97\xba\x3d\x80\x06\x52\xb0\x1a\xbc\xd4\x70\x23\xe9\xa6\xd0\x45\x6d\x18\x8f\xd3\xba\x0f\xc5\x29\x0f\xa6\x82\xa8\x48\x0d\x44\x29\x95\xe8\x1a\x42\x55\xa9\xd2\x48\xb8\x12\xf5\x7b\xc6\x2b\xf2\xfd\x88\xc7\x4c\x20\x58\xcf\x20\xfb\x35\x50\xee\x15\x29\x5c\x1f\x7b\xa4\x45\xbf\x20\x63\x97\xed\x72\x50\xdb\x9b\xe2\x7b\x55\x2e\xb4\x0f\xf1\x78\xee\x78\x9c\x66\x73\xb0\x04\xa7\x61\x3f\x98\x0b\xc2\xec\x28\x40\xae\x1e\xaf\xd4\x5c\x0c\xe9\x68\x8e\xe0\xe1\x1c\x8a\x7c\xe9\x6d\x3a\xe7\xa7\x40\x81\x41\x6e\x7b\x17\x63\x1d\x23\xb8\xfc\x3a\xdc\x81\x94\x3a\x90\xbb\xbe\x15\x64\xa3\x1c\x41\xf6\x77\xe1\x70\xb8\x15\x00\xf1\x71\x1a\x94\x40\x42\xee\x0c\x88\xe2\x51\xa3\xc6\x09\x46\xd8\x29\x4e\xc9\xec\x23\x56\x3e\x59\xd6\x81\xe2\x99\x9f\x97\xe4\xc5\xb6\xb4\x0b\xd0\xdc\xa2\xfa\xb6\x2e\xa7\xf6\xb7\x9d\x55\xce\x5d\x27\xaa\xbc\x92\x49\x17\xb6\x7d\xf5\x14\xaa\x30\x51\xd9\xb4\xd3\x95\x57\x55\xfe\x02\xb4\x7d\x58\xad\x91\x21\x08\xdc\x22\x04\x95\x9c\xc8\xb6\x78\x0c\xcc\xfb\xc7\x09\x60\x2e\x7a\x2b\x3b\x64\xae\x9c\x3f\xba\x64\xd4\x62\x16\xe9\x51\xd8\x7f\x33\xea\x17\x40\x1c\x73\x9e\xcb\x3b\xaf\x0e\x76\xd1\x1c\x97\xce\xb3\x12\x9d\xd7\xf7\x45\x33\x7b\x0a\xdd\x29\xee\x98\x17\x64\x9d\x67\x8d\x0b\x83\xef\x4d\x05\xa9\xae\x6a\xae\x16\xb4\x60\xf7\xa6\x94\xd3\xf2\xb9\xca\x49\x79\x8d\x96\x4e\x7c\x56\x0e\x02\xdc\xff\xc7\x7e\x74\x31\xc7\x06\xff\xfa\xf4\xf4\x29\xf6\x64\xed\xb9\x50\x27\x06\xaa\xf0\xe1\xbf\xe9\x4f\xa3\x34\xe5\x95\x41\x16\xd7\xf5\xb2\x02\x13\x95\x61\xda\x00\x32\x99\x4f\x04\xfb\x36\x5f\xbc\x84\x9b\xdf\x71\x5b\xbd\x61\x98\x1f\x87\x0a\xa0\xab\x99\xf8\x1a\xa8\x57\x93\x0b\x37\x8b\xfd\xa6\x7a\xaf\xcf\x5d\xdf\xb7\x54\x97\xbe\xb2\xe1\xe1\xa3\xf8\x2c\x9a\x56\x5d\x8a\xf3\xd0\xaa\xf4\xf0\x81\xf5\xb1\x3c\xc6\x2b\x51\xbb\xe7\x6a\xa0\x4e\x95\x5f\x63\x9a\x2b\x9c\x6a\x57\x5f\xa2\xf5\x9f\xbf\x08\xd0\x79\x6b\x73\x46\x0e\x40\xe8\x2d\xa6\x42\xb4\x58\xcd\x5a\x3e\xf6\x88\xed\x73\x91\x30\x72\xac\xec\x65\xe0\x38\x83\x63\x2a\x92\x9a\x2e\x55\xda\xe9\x94\x76\x5c\xf5\xb6\xbd\xa6\xf5\x0a\xb1\x8c\xf1\xef\x2a\xf7\xf3\xcd\xeb\xc0\x9b\x1b\x23\x59\x57\x76\xee\xb4\x7d\x3a\x65\x17\xc0\x7e\xd5\x4d\x3d\xad\x45\x38\x33\x75\xda\x18\x2a\xd8\x48\xa9\x73\xed\x4e\x56\xc2\xbc\x62\xa1\x16\x8c\x1e\x32\xe5\xbb\x1c\xba\x00\x50\xc3\x3f\x54\x39\x14\x46\x90\x56\xcf\x3b\x8d\xa0\x80\x36\x2c\x2c\xd8\x7a\xac\xce\xb4\x6c\xae\x25\x7f\x12\xe8\xed\x4d\xeb\xb2\xda\x0a\x44\x99\xb5\xbc\x45\x34\xa4\x16\x55\xc1\x99\xb3\x26\xe6\x86\xf8\x72\x65\x23\x15\x5a\x5a\x2a\xb5\x84\xb6\x62\xa2\x9e\x0e\xd0\xcb\x52\x37\x73\x8e\x2b\x66\x5d\x2a\x26\x72\xf1\xca\x4f\x3b\x31\x8b\xf6\x15\x52\xbc\x70\xed\x4f\x33\xc9\xba\x4e\xa0\x8d\xb7\x54\xf3\x35\x98\x47\x65\xa6\x2a\x28\xea\xd2\x95\x6b\xaf\x41\x91\xc8\xa1\xbb\xf2\x60\x0c\x57\x4a\x3e\x84\xed\xec\x62\x18\xd4\xd1\x5a\xd7\x21\xef\x22\x3e\x0d\x12\xf4\x32\xf3\xde\x6b\x1c\x85\xfd\x7e\x10\x35\xcc\xab\x0f\x5e\x83\x97\xad\x71\xa5\x1a\xe4\x32\xa5\xc6\x8c\xfe\xc1\xe5\x59\xd8\xcf\x8e\xbc\x46\x7b\x69\xe9\x37\x0d\xa1\x9a\xb6\x38\xcf\x6e\xb3\x31\x3a\xc7\xba\xe0\xa4\xf6\x6d\x5c\xb7\x40\x4c\x95\xae\x70\x76\x26\x67\xcd\x68\x05\x42\x89\x29\x1f\x01\x92\x20\x55\x05\x48\x65\x61\x3d\xcc\xb6\x24\xe7\xb3\xa3\x98\x9c\x53\xad\x9f\x92\xf3\x95\x46\x04\x37\x73\x43\x3b\x84\xbe\x76\x17\x15\x58\x59\x33\xfb\x48\x3c\x9d\xd9\xd5\x55\x39\x4d\xd3\x6a\xc4\x81\x99\x80\x2f\xb5\xb4\xf1\x65\x4e\xa3\xdb\x73\xaa\x5f\x76\xeb\x5e\xa2\xab\x7c\x80\x79\x7a\xcd\x71\x57\xa1\x8d\x10\x2e\x35\x65\xaf\xdb\x71\xe8\xe6\x3b\x52\x27\x98\x32\xd5\x81\x5c\x58\xef\xfa\x4e\x72\x6b\xc7\x71\x9c\x1d\x99\x45\x79\xa7\xad\x03\xb9\xe5\x60\x76\xe1\x4c\x2f\x41\xb5\xa7\xd6\x56\x75\xd8\x97\xc7\xcc\x9a\x0e\xac\xd9\x9f\x5d\x19\x79\xcd\x9d\x55\x55\x91\x8b\xd1\xb8\x12\xb3\xc0\x81\xbd\x14\x53\xd8\x1f\xec\xe2\x1e\x99\x8c\x96\x56\xca\x58\x44\x2d\x5d\x95\x1c\xff\x69\x14\xb4\x6e\xc8\x43\xf4\xda\x4b\xe2\x33\x18\x94\x5e\xbb\x2d\xca\xcc\x4f\xef\xb7\xa2\xc2\xf9\xf4\xbe\x16\xc4\x2f\xf5\x96\x97\x50\x2d\xac\x7d\xaf\xca\x6e\x65\xca\xed\x52\x0b\xf9\x9f\x6f\xbe\x5b\xdf\xf2\xda\xa2\x28\xf4\xf7\x96\x01\x53\xa8\xb8\xe6\x34\xe1\x37\x04\xc6\x8c\x4d\x65\xae\x5f\x03\xe4\xf8\x52\x27\x5d\x91\xe3\x0e\xd1\x24\xb1\x1c\x37\x2d\x44\xd2\x49\x17\xc7\x2e\x06\xd1\xf5\x25\x06\x7f\x87\x1f\xf4\xe6\xa9\x15\x14\x3a\xc1\x8a\xdf\x1d\xcb\xb8\xd9\xf6\xfc\x15\xf4\xee\x99\x62\xfc\xf3\x9c\x6a\x86\xcc\x49\xab\xd0\xdd\x85\x85\xf1\xca\x52\x37\x94\xe3\xc5\xb6\x57\xfc\xcc\xbd\x5f\x58\x48\x1f\xe4\x7d\xa3\x18\xe9\x69\xb3\x8d\xd1\x11\xac\xcd\x72\x59\xd1\x8b\xf0\x60\x5c\x23\x40\x45\x92\x2b\xc5\xac\xfe\xb2\x3a\x7b\x05\xde\x78\x59\x36\x45\x91\xb6\xf2\xa1\xcd\x53\x90\x46\xad\x35\x97\xbb\xc1\x65\xbf\x37\xca\x4d\x6e\xf9\x6b\x60\xbe\x06\x45\x77\xc5\x91\x16\x59\xa3\x13\x40\x0a\xfb\x58\x78\xa1\x62\x4b\xe4\xd4\x5d\x52\x0c\x09\x09\xb5\xe4\xf1\xe6\xcb\x0a\x68\x25\xc1\x3a\xf9\x9c\xe4\x50\x7b\x4b\x9d\xf8\x81\xae\xb4\x13\x37\x9b\x2e\xf3\x51\x22\x94\xb7\x4f\x26\xd9\x0e\x26\xf6\xa0\xb5\x80\x53\x79\x63\x7a\x0a\xae\xa2\xd6\xfe\x7e\x90\xbe\x88\xfb\xe3\x61\x80\x36\x2c\x11\x3a\xe2\x24\x5e\x68\x63\x4f\x26\x96\x88\xc0\xfe\xa0\x16\xe0\xab\x9b\x2f\x80\x7b\x79\x55\x95\x36\xd4\xa8\x59\x57\x14\x37\x48\x81\x94\x0e\xcd\x9d\x61\x78\x70\x27\x8c\x28\x4c\x4a\x64\x44\x0e\xf9\xa7\xf5\xf3\xa0\x37\xc6\xba\xd6\xa3\xd3\x30\x89\x23\x32\xa1\x42\x20\x13\x01\xce\x07\x68\x30\x4c\xd7\xa5\x8a\x55\xd1\x16\xe8\xa8\xae\x80\x7b\x38\xa1\x68\xac\xf9\x11\x0a\x4a\xb0\x0b\x4f\xc3\x34\x8b\x93\x0b\x72\x68\x37\xa7\x5c\xe3\xcd\xf9\x73\x50\x4d\x83\x82\x60\xf2\xe6\x95\x6d\xa1\x14\xf6\x8f\xac\xfc\xe8\x6b\xa5\xa4\x8c\x77\x5d\x37\xbd\xdf\xde\x13\xb5\xa3\xf4\xda\x5f\x13\xa4\xa8\xd1\xb5\x9d\xb1\xd7\x35\x20\x09\x35\x8f\x63\x0b\xba\x1f\xa4\xb8\x05\x43\xd7\xa8\x6d\x88\xb1\xe8\xc9\x25\x31\x94\x26\x08\xe9\x70\xa5\xd7\x69\x36\x7b\xb8\x8b\xc6\x32\xdc\xe9\xed\x89\xf9\x31\x3a\x6f\xe3\x75\x47\x9f\x11\xe8\x38\x2d\xce\x1e\xc7\x00\x6f\x29\xe2\x49\xe2\x8c\xa9\x39\x13\xa3\x3b\x6e\x25\xd4\x56\x4b\xf9\x22\xc0\xa3\x10\xd3\x4a\x62\xf4\x51\xb5\x83\xa8\x3b\xe4\x0c\x02\x63\x24\x4b\x1f\xdd\xfe\x25\x30\x78\x72\xe9\x98\x3a\xa3\xd6\x08\x43\xae\x05\x79\xad\xcc\xad\x0b\xc4\x91\x88\xc4\x0e\x90\x55\x7b\xda\x91\x05\xba\x39\xe7\xee\x98\x3a\x07\xb5\x75\x0e\xae\xab\x73\xb0\xa7\xbd\x5b\x94\x8b\x66\xba\xa8\x46\x60\x8e\xba\xc5\xb2\x7b\xec\x03\x59\xa9\xcc\x14\x99\x51\x78\x20\x9d\xcc\xf6\xe3\x11\xd8\x4c\x4e\x63\xbd\xe7\xe8\xdd\x87\x97\x22\xec\x34\xc2\x71\x90\x25\x63\x99\x9b\xc3\x0d\x16\xd7\xc6\xf0\xe1\xa0\x38\x97\xb9\x0b\xff\xa5\x4e\xf4\xc0\x78\xf0\x8f\x00\x2e\xd8\xbe\x12\x92\x56\x60\x02\x96\x49\xfb\x61\x32\x01\xfa\x2a\x69\xd9\x22\x48\x04\x09\x0d\x62\x21\x61\x34\x4d\x8c\x72\x93\xb4\xb4\xb8\x52\xa2\x27\xf0\x7a\xb1\x27\x22\x2e\x00\xf7\x28\x24\x4a\xd9\x5d\x71\xc0\xb1\xd2\xf3\x00\x0b\x99\x63\x19\xf4\x93\xcf\x10\x7a\x87\x41\x74\x02\x8a\xa8\xa2\xc4\x85\xaf\x60\x15\xde\xa0\x92\x14\x09\x04\xeb\xe7\x81\xe3\x7e\xc7\x30\xef\x4a\x8b\x55\x13\x25\x50\x16\x7d\x39\xc8\x40\x3f\xe3\xd2\xca\x88\x9f\x4e\xc6\xe8\x91\x31\xe1\x07\xde\xbf\x70\x6c\xf5\x8e\x46\x67\x13\xe8\x16\x62\xe7\x12\x86\xe4\x35\xd0\xb7\x22\xb9\x1b\x6c\x54\x84\xb3\xc5\x45\xf0\xb5\x4f\xcd\x6f\xb1\x7a\x0e\x93\x6a\xf6\x96\x79\x17\x93\x46\x14\x0c\x68\x49\x8c\xcd\x95\xdd\x51\xe1\x72\xf0\x2a\x4d\x31\x60\xa9\x8b\x47\x2d\xc3\x50\xa5\x18\x03\x21\x0f\x28\x79\xb5\xc7\x1e\xdf\x2c\x78\x93\x32\x9e\x93\xcf\x16\x60\x1b\x08\x42\x6a\x94\xd0\xeb\xa1\x2d\x94\xd5\x22\x32\x82\xb2\x97\x3d\xf6\xf3\xa7\x44\xa5\x34\x3f\x89\x97\xf0\x44\xd9\xd2\x43\xe4\x1d\x7c\x0a\xb0\x61\xaf\xdc\x92\xcd\x20\x53\xd5\xe9\xf2\xba\x8c\x8e\xbe\x40\x95\x3c\x45\xb4\xf4\x33\x2b\xc1\x32\xa6\x12\xf2\x98\x4a\x7c\xa3\xd7\x71\xa5\xa2\xba\x1a\xec\x02\xa6\x16\xa5\xa1\x8d\xee\x07\x6f\x54\x89\x95\xdf\xd4\x71\x18\x3f\x2c\x5f\x36\xd3\xc7\xc1\x99\x4b\x37\x48\xa8\x56\xd4\xac\x8a\xb7\xdc\x86\x15\x5d\xae\x51\xef\x9e\x7a\x29\x58\x90\x68\x6e\xe4\x6a\x76\xe2\xce\x1e\xf2\x09\x8d\x22\x7a\x5a\x72\xb0\x62\xa2\x24\x38\xec\x49\x1b\x9d\x23\x35\x9c\x9d\xdf\xdd\xe9\xfe\x7a\xaf\xe9\x36\x5c\xaf\xf1\x45\x83\x74\x29\xf5\x77\xf4\x6f\xe3\xe3\xdd\xdc\x40\xef\x05\x94\x63\x77\xb7\xd1\xcc\x80\x0e\x18\xa1\x23\x99\x4b\x76\x72\x9c\x90\xe3\x1f\x4b\x2d\x3e\x42\x0d\x76\xd1\x08\x1b\x18\xf3\x0f\x4e\x26\xc5\xa8\xc2\xd0\x67\xaa\x07\x58\x38\xd7\x48\xac\x47\x07\x48\xd7\x80\xf1\xb5\x45\x76\xe6\xad\x35\x0d\x4e\x18\x62\xdc\xf1\x1c\xb4\x64\x5f\x5d\xfc\x6e\xff\xd6\x9e\x4a\x2d\x2d\xde\x87\x87\x2f\xdc\xc9\xce\x17\x2d\xc7\xdd\x45\xd3\x81\xdd\xe6\xe4\xf2\xea\x77\xb7\xd0\x7c\x60\x3c\xbd\x4c\x77\xef\x8b\x9d\xee\x5e\x17\x0b\x62\xce\x9e\xbc\xb3\x8b\xff\xba\x13\xfc\xb3\x7b\x87\x7e\xc8\x00\x01\x7e\x61\x2e\xdc\x5b\x77\xc4\x08\x03\xf1\x0d\xe4\x65\x98\xae\x1e\xa4\xf1\x70\x9c\xd5\x31\x24\x1a\x77\x68\x46\x73\x57\xf5\x57\x02\xdd\xf5\x94\x45\x1c\xda\x15\xbd\x31\x21\xd8\xbd\x83\xee\x05\xa0\x34\xc6\x6f\x15\xf6\x05\xc6\x73\x59\x63\xf1\x83\xbb\xa2\x95\x4f\x77\xb1\x54\x5a\x27\xd6\x63\x5b\x0d\x34\xdd\x51\xeb\x88\xd0\xcb\xaa\x42\x60\x94\x41\x0e\x8c\x1d\xb2\x07\x27\xe3\x5b\x0a\x01\x9a\xd2\xb0\xcf\x3d\x5b\xc6\xda\xcd\x77\xc9\x76\x20\xc5\xbd\xe2\xef\x04\xcd\x36\x05\x3a\x42\xb6\x28\x2e\x6b\x6d\xc7\x00\xa4\x4f\x60\xc1\x3a\xfa\xe2\xab\x4c\xcd\x38\xdf\xd4\x7c\x33\x20\x01\x14\x03\x6e\xcf\x7b\x55\x34\xba\x38\xe3\xb1\xe2\xda\x00\x69\xa3\xb3\x98\x80\xe3\xf0\x4e\x47\x07\x46\xc4\x5a\x2d\x54\x43\x45\x33\xd7\xc1\xe6\x91\x74\xba\xfd\x02\xc3\xc1\x47\x87\x73\x8d\xdf\xa4\x8d\x39\x9a\x98\x00\x8e\x35\x99\x6e\xe0\x15\x44\xef\x6f\x03\x7d\xa6\x18\x7f\xbe\x8e\xda\xc1\x7d\x91\x04\xf2\xc9\x78\x4b\xfb\xd3\x75\xa8\xc9\xae\xe3\x53\x03\x3b\x70\x97\xef\x09\xdd\xa4\x9f\xb7\x47\xe5\xe7\x7e\x3d\xf7\x9b\xb4\xdc\x56\x84\x91\x48\x3c\x2e\x8e\x91\x96\x6c\xdb\x9a\x3b\x88\x52\xd8\x17\x52\x9d\x9c\x53\x2d\xe8\x30\x0f\x1d\xb0\xb0\xe0\xb3\x3f\x59\x07\x83\x5e\x40\x15\xf6\x3d\x57\xb7\xd3\xf2\xc5\x18\x0a\x74\x99\x48\x05\xca\xb9\xf3\x5d\x36\x28\x5e\x92\x30\x57\x11\xf9\x94\x0b\xba\xb1\x83\xd1\x0d\xbc\x48\x4b\x38\x7d\xa5\xc3\x11\x0e\xd0\x69\xd4\x25\x51\xde\x8f\xe3\x04\x7a\xec\x35\x0e\xa0\x86\x4f\x41\x96\x36\xae\x72\xce\x53\x77\x50\xbc\x93\x91\xbf\xd7\x6d\x34\x13\xaf\xf2\xbe\x00\x80\x07\x08\x80\x8b\xa0\xc5\xbb\x77\x5f\x9c\xa4\xde\x97\x4b\x33\xf1\xf6\xe5\x1a\xa5\xec\xeb\x48\x1c\x85\x51\x19\x10\x96\x83\x3c\xa0\x66\xcc\x1d\xa0\x8c\x60\xee\x10\xda\x4b\x80\x2e\x71\x50\x7f\x44\x5c\x0e\xfc\x61\x7a\x31\xf5\xee\xdc\x09\xf6\xba\x96\xcc\xf0\x01\xc2\xde\xdb\x2b\x73\x29\x8c\x7d\xc8\x7a\x78\x47\xfe\x69\x00\x58\x67\xe3\x76\x33\x68\xde\x6e\x90\x68\xf0\xb6\xab\x19\xed\x82\xee\x29\x2f\x6c\x69\x84\x76\x73\x80\xa2\x0f\x85\x13\x70\xb8\xbf\x02\xd3\xc7\xe7\xbb\x8b\xbb\xe9\x2d\xdf\xcd\x19\x20\x62\xea\x98\xbd\xaf\x11\x61\x59\xae\x51\x37\xbd\x86\xe6\x61\x97\x6d\xb1\x56\x34\x55\x48\x5e\x60\x23\x79\x51\x95\x0e\x5d\xae\xd1\x7a\xab\x2e\x92\xf8\x05\xb3\xff\x23\x61\xf6\xd3\xb7\x7e\x3a\xfd\xb6\x1f\x17\x3f\x9d\xf9\x49\x84\xa6\x93\x2e\xdc\xc4\x15\x62\x61\x38\x9b\x58\x40\x66\x19\xd0\xc2\xc3\x0a\xd1\x50\x24\x18\xb2\x23\x4d\x2e\xe4\x17\x9e\xec\xb5\x2a\x57\xad\x63\xf2\xab\x6a\x60\x2c\x71\xa2\x18\xcb\x0f\x03\x38\x5e\x61\x9c\xc8\xf9\x79\x45\x6e\x18\xf2\x1a\x5e\xc5\xfa\x95\xa6\xb1\xe1\x9d\xcf\xef\x90\x5f\x80\x9a\x25\xa9\x7e\x7c\x1e\xc0\x39\x95\x63\x5b\xaa\x97\xc8\xa1\x4d\xb4\x28\x7a\x05\x99\xd3\x51\x9f\x54\x22\x2a\x14\x0b\xde\xb5\x4e\x60\xef\xe1\x0c\x8e\x25\x9e\xd5\x96\x55\x8c\x75\x0a\xf0\x44\xf8\xa8\x4e\x00\x80\x40\x43\x1d\x46\x61\x73\x0e\x03\x7a\xa2\x2e\xbd\x42\xbf\x7b\x95\x7c\x26\x9e\x1f\x9c\x40\xea\xa4\xb6\x96\xac\xf4\xd0\x38\x29\x7a\xc0\x6d\x16\xac\x2b\x70\x81\x50\x38\xd5\x94\xb7\xe7\x68\xb1\x00\x68\x99\x0f\x00\xbc\x6e\x63\x40\x25\xf8\x46\x8b\xa7\xbf\xe1\x03\x7c\x5b\xb9\x0d\xc4\x93\x9e\x23\xe6\x8c\x73\x0b\x95\x39\x42\x78\xa0\xb0\x0c\x51\x31\xd1\xe5\x78\x47\x97\x58\x29\x8a\x08\x95\xd6\x4c\xd2\x09\xbb\x63\x15\xfc\x8a\x7c\xaf\x07\x11\x33\x3d\x26\x93\xc2\x23\x1a\xc2\x08\x52\x71\xb2\x00\x30\x4e\xb4\x95\x87\xd8\x4f\x73\x56\x0f\x71\xb9\x50\x11\xca\x87\xcc\xa8\x09\x45\xeb\x75\x3b\x65\x95\x8d\x39\x1d\x83\xa6\x33\x17\x02\x70\x4a\xe7\x78\xf7\xf5\x01\x15\x0f\x8b\x5d\xe9\xb0\x2f\xe4\x80\xbd\x25\xfa\xf4\x31\x3b\x9a\x4c\xe2\xce\xbc\x8f\xdd\x34\x1b\x93\x1f\xf4\x96\xec\xfa\xa8\xdf\x43\x79\x3d\x40\x20\xbc\x5e\x2b\xc7\x67\x1d\xdf\xed\x86\x0b\x0b\xa9\x83\x2c\xe4\x50\xd5\xb7\xa4\xd2\xfa\x7c\x68\xe5\xb9\xdb\x38\xec\x1e\x83\xc6\x28\x40\x05\x2f\x8d\xb4\xe8\x01\x62\xba\x43\xda\x2a\xdc\xed\xb9\x84\x09\xcd\x74\xee\xcd\xd6\xf3\x1c\xbb\x4a\x6f\xc3\x09\xe6\xd6\x10\xd1\x09\xbb\xbd\x16\xa2\xcc\x0e\xbf\x12\xbe\x8b\xfd\x6c\xfa\x22\x28\x30\xaf\xe6\xef\xec\x7e\xa1\x3d\x5e\x92\x25\xa8\xdf\x94\x40\xce\xf0\x0a\x0e\x49\x3f\x2c\x73\x10\x36\x04\xb5\x07\x58\x58\x13\x54\xa8\x19\xa3\x53\xf0\x59\xa5\x14\x1d\x53\x0a\xb7\x40\x27\x94\xb0\x62\x98\x22\x67\x98\x17\xef\x3a\xa9\xda\x2a\x61\x81\x41\x26\x60\xfc\x73\xc7\xfe\x45\x7e\x2b\x1f\x43\x37\x60\x3e\x7c\x38\xdf\x51\x30\xa7\xf2\xf2\xfa\x37\x44\x08\xa8\x42\xa1\xbc\x1c\xba\xde\xb0\xc8\xb0\xcb\x1b\x2a\xb0\xcd\xae\x6b\x09\x5f\x0f\x30\x77\xa1\xad\x42\x15\xd0\x98\x08\x6d\xa0\x01\x08\x23\x90\x81\x55\x37\x23\x8a\x35\x39\x82\x33\x02\xf0\x4a\x44\x2c\x05\x1a\x02\xf8\x15\x89\x1c\x69\xf8\x35\x34\x90\x41\xc5\xf1\xb6\xc6\x55\x07\xc5\x0c\xa2\x69\x9d\x13\xc7\x47\x8c\x08\xd0\x42\x33\xd3\x24\xa5\x76\x4b\x55\xbf\xb4\x87\xf1\x13\xea\xd6\xe5\x6b\x2b\xdf\x0a\xfa\xb0\x61\xd1\x03\xd8\x67\xd6\xcb\x00\x45\x1d\xa1\xa0\x35\x48\x30\xe6\x23\xec\x4f\xa1\x36\x97\x8d\xe0\xd1\xad\x8b\x38\x36\xb7\xe5\xa0\x71\x3a\x87\x7c\x00\xf4\x07\xbd\xbd\x07\x8c\xfc\x4c\x26\x78\x6b\x63\x1f\xab\x5c\xa3\x61\x0d\xd7\x68\x26\x86\x36\x1d\xef\x15\x35\xf7\x32\xd4\xf6\x35\xa2\x5a\x35\x12\xaf\xeb\x64\x36\xf3\x45\x81\x4d\x96\xf3\xf2\xa4\x82\x59\xf8\x50\x96\xc6\x28\x8e\x4a\x4a\xa1\x4c\x55\x12\x09\xd7\xb2\xd3\x6c\x43\xa4\x2c\xb6\x49\x2a\xa3\x22\x9e\x70\xa4\x4c\x55\x67\x48\x41\x2c\xea\x22\x26\x67\xb5\xb0\xe1\xca\xbd\x11\xaf\xe2\x33\x44\x17\x8a\x03\x7a\x18\x64\xef\x48\xde\xc0\xed\xbd\x8a\x99\x61\x45\x98\xd2\x25\x4a\x6b\xc3\x1e\x32\xe8\x82\x5e\x9c\xf4\x8b\x59\xaa\xca\x2a\x2c\x32\x57\x72\x0e\x7d\x6f\x17\x5e\x02\xa1\xae\x95\x57\xec\xd7\x44\x9b\x3b\xb6\x6e\x5d\x6d\x23\x05\x95\xb8\x3f\xa0\x2d\x16\xb8\x5d\x5d\xab\x6a\xa9\x43\x4d\x2a\xa6\x9a\xb6\x04\xcd\x75\x02\xf5\xea\x38\x2e\xdc\x71\x05\x61\x0f\x37\x39\x77\xa0\x32\x94\xe5\x3d\x37\xd1\x7f\xdc\x1f\x93\x26\xaa\xd2\xab\xba\x89\x96\x6a\x4d\x31\x8c\x6f\x5c\x78\x53\x98\x50\x74\x71\x6c\xa9\x57\x20\x59\x6f\xa9\x22\x5f\x37\xe6\x0e\x45\x01\xb5\x2b\xd7\xab\xe6\x4c\x2f\x5e\xcc\xa2\xb4\xf2\x72\xc4\x96\x5f\xb0\xcf\x6d\x74\x91\x5d\x65\x42\x4f\xdb\xb0\xde\xdd\x02\x94\xf8\x49\x32\xb1\xe5\xeb\xe4\xbf\x3f\x07\x43\x1b\x06\x50\xe4\x67\xcf\xe6\xde\x06\xd9\x1a\x2b\xf5\x11\x43\xdb\x35\xe5\xc9\x8d\xf4\x4f\xa9\x03\x0b\x9a\x7a\x8a\xdc\xaf\x1b\xd7\x42\x42\x2c\xae\xa3\xc4\x73\xb9\x61\x15\xcc\x13\xe1\x1a\x18\x7f\xff\xec\x2a\xb8\x18\xd6\x01\xd8\x62\x0f\x3d\xe3\x7c\x0e\x77\x5f\x97\xd1\x3c\xf5\x9b\x30\xc7\x3f\x43\x38\x9d\x9f\x47\x22\x14\x14\xf7\xc0\x3f\x80\xfa\xb7\x02\x3f\x8d\xd9\x65\x8e\x92\x0e\x05\x19\x40\x2b\x8e\xfb\xa8\x9c\x94\x59\x96\xf2\x6b\x48\x45\x0d\x87\xbe\x82\xca\x9a\x47\xa3\x91\x00\xd7\xb6\x71\xe7\x06\x0a\xbe\xf4\x2d\x10\x66\xb5\xae\xd5\xef\xec\x0e\xa1\x6e\xc2\xea\xc3\xcd\xad\xd7\x08\x9e\xec\x4a\x35\x12\x50\xd1\x0e\xc9\xab\xa0\x48\xe4\x5a\xc6\x51\x2a\xde\xa3\x01\xc8\x32\x78\xcb\xcb\x85\x54\x00\xd1\x91\x52\x0b\x1c\x96\xa8\xec\x0a\x06\xe3\x76\x87\xd5\x90\xa5\x8a\x0d\x3b\x99\x64\xf6\xa8\xdc\x00\x3e\x74\x98\xab\x8a\x96\x6d\x0a\x7b\x76\x29\xf8\xaa\x7e\x42\x7c\x07\xe3\x8e\x07\xa8\xd1\xa4\xde\x29\x92\xe2\xc1\x5d\x80\x71\x8e\x0e\xca\xea\x43\x7f\xe0\x0f\x73\x69\x29\x00\x0a\x74\xd1\xa1\xee\x67\xe5\xb8\xb6\xdc\xcb\x42\xfc\x2b\x7b\x0c\x3f\x71\x04\xa1\xa6\x04\x68\x04\xe6\x89\x31\x36\x1c\x80\x79\xa5\x07\x70\xef\x9a\x01\x84\x34\x80\x8a\xd1\x76\x61\xdb\x79\xed\xaf\x84\xbd\xe9\xbc\x65\x34\xde\x5e\xbe\x99\xb2\xc5\xe5\xab\x37\xdb\x4f\x3d\x15\xcf\x60\x6b\xfd\xd5\xf3\xd5\xb5\x75\x2f\x8f\x6b\xf0\x6a\xf3\x95\x47\x21\x0f\xec\x13\xa8\xd9\x68\xd7\xe9\x28\xe4\xf0\xb8\x75\x47\x05\x6a\xb8\xf3\x3c\xee\x51\xaf\x57\xf9\x99\xc1\x73\xdd\x2d\x55\xba\x3d\x53\xb8\xa3\x7b\xc8\x41\xb8\xec\xf9\xd0\x44\xd2\xa2\x7e\xab\xb4\xee\xb7\xd2\xcd\xd0\xca\xcd\x0e\x06\x13\xea\x1c\xc0\x95\xf2\xa9\xa3\x4b\xc1\x78\xb2\x6e\x39\x5f\xd6\x3a\x17\x59\xeb\xc2\xad\xad\xe0\xaa\x06\xfa\x4c\x1f\x8f\xb7\xfc\x5b\x9c\x9a\x9b\xc9\x5e\xaf\x19\xb8\x7b\x59\xdf\x9f\xea\x52\xdc\xbd\x4e\x32\xc8\xed\xfd\x51\xf9\x99\xe1\x5f\x45\x7e\x66\x5c\x9d\xd3\xba\x68\xe7\x0b\x0b\xca\xff\x4a\x50\x3f\xc1\xdb\xe8\xce\x64\x0e\x16\x35\x09\x80\xde\x82\x69\x23\x06\x9c\x32\x7c\x3b\x08\x48\x98\x46\x76\x6f\xa6\xaf\x82\x68\xf4\x46\x53\xb7\xe0\x76\x2c\xfd\xb1\x92\x37\x95\x62\x3c\x78\x71\x69\xa1\x7e\xde\x25\x93\xa9\xd0\x79\x33\xd7\xa8\x74\x3f\xc3\x42\x9d\x0c\xc9\xf1\x8a\x6a\xed\xef\x53\xa5\xfb\xfb\x12\x11\x59\xdf\x12\x5b\xd8\xea\x1a\x99\xb5\x1b\x02\xd2\xbc\x62\x4b\x00\x16\xb1\xa9\xb8\xf6\xf5\x2e\x69\x0c\x6f\x13\x91\x5f\x11\xc2\x8f\x62\xdf\xb1\x72\x76\x0d\xef\xd0\xc6\x29\x8a\x4a\xda\x44\x03\x07\x57\x8e\xdf\x5a\xd3\x98\x7a\x59\x89\xc2\x56\xd5\xbc\x7b\x33\x41\xce\x5f\xd4\x89\xfa\xab\xbe\xb9\xb4\x07\x38\x1b\xaf\xf7\x2d\x81\x18\xeb\x72\x27\xb9\xe7\x00\xcd\xb0\x1e\xff\x9c\x1b\x31\xe4\x8d\x08\xbb\x28\x75\x3b\xe3\x96\x71\x27\x20\x39\x6c\x4c\xac\x84\x93\x82\x78\x39\x71\x8b\x04\x73\x42\x6f\x40\xf3\x42\x71\x06\xf1\x19\xba\x53\xa0\x3e\xc6\x9a\x9f\x47\x46\xa8\xf2\x52\x67\xf5\x6d\x1c\x60\xac\xae\xa0\x02\x06\x2c\x72\x99\xdb\xdd\x2f\x45\x79\x5a\xbc\xbb\x5f\xe1\x9e\xfe\x1c\x01\x5b\xc9\xa1\xdf\xc1\x38\xcb\xe2\x68\x8a\x33\x4a\x58\xae\xe3\x20\xf3\x9f\x05\x17\x84\x1e\x0d\x33\x95\xea\x65\xc9\x50\x25\x49\x37\x10\xd2\x8c\x3d\xd7\x80\xcd\x9f\xf3\xe0\xf8\x7f\x15\xaf\xa2\xf4\x17\x68\xa1\xa1\xc5\xd8\xbe\x8a\x7a\xb3\x45\x8e\xc3\x1a\xc8\x32\x9a\x0e\x34\xe2\xcf\x06\x1a\x29\x03\x0d\x3f\xbf\xbd\xf8\x54\xaf\x0d\x43\x8c\x57\x58\xf5\xf7\x42\x3c\x1e\x11\xc1\xc6\xe9\x14\xec\xab\xa8\x00\x49\x9f\xaa\xaf\x29\x18\xdf\x3c\x3b\x60\x4d\xe8\xaf\xe3\x20\xbf\x74\xbe\x8d\x87\xcf\x00\x95\xe0\x94\xdc\xc1\xe0\x87\x25\x97\xc2\xf9\x61\xe0\x58\x32\xf9\xc6\x2f\x8a\x6b\x0e\x9b\x29\x52\xb6\xca\x33\x75\xe6\x2c\x03\xbc\xd8\x36\x05\x63\x3e\xb4\xfd\x86\xb8\xd1\x16\xaf\xfc\x30\xc8\x50\x79\xef\x9a\x0b\x7c\xaa\xca\xdf\xe7\x36\x6c\xb7\xbb\xa6\x6d\x89\xa6\x4a\x1e\xeb\x0c\x8f\x0a\x52\x48\xa8\x85\xd9\x13\x6c\x1c\xe7\xb2\x44\xb2\x81\x47\x20\x2f\xea\x53\x0e\xd3\x1a\xf2\xdf\xad\x5e\x58\xe5\x3f\x6f\x12\x72\xce\xc8\x4f\x9e\x84\xa9\xc8\x13\x0f\xbf\x87\x02\x89\xbc\xb4\xb8\x3c\x42\xd5\x4c\x3d\x70\x5a\x00\x57\x94\x6c\xb7\xec\x79\x25\x7b\x2b\xda\x94\x9e\x25\xaa\xa6\x17\x36\x13\xc5\xe8\xe8\x64\x6a\xaa\xc8\x72\x49\x6d\xbb\xba\x19\x6e\x91\xc1\x93\x2c\x64\x87\xfb\xbd\xf5\x68\xf3\x45\x0b\x3d\x4b\xd4\xe0\x7c\xae\x46\xfa\xc6\x36\xd2\x37\x6a\xd9\xec\x40\xa9\xd9\x81\xc3\x3a\x76\xe0\xc8\xbe\xe4\x4b\x4b\x0a\x25\xf8\xbe\xb7\xfd\xe9\x64\x31\xbc\xb6\xbc\xfa\xe8\x3c\x42\x55\x5f\xf4\xd5\xc3\x6b\x85\x25\x08\x2a\x09\x5a\xa9\xfc\xd1\x1a\x69\xfe\x52\x4f\xee\x90\x75\x6f\xa0\x8b\x45\x9c\xa1\xdc\xcb\x06\xbf\x68\x08\xdb\x8a\xce\xc6\x27\x46\xb5\xf8\xc4\x8d\xd5\x76\xee\xde\x48\x9b\xe6\x17\x4c\xf9\x17\x4c\xf9\x2f\x11\xa6\x7c\x9d\xd8\xf2\x97\x3d\xfd\x4f\xd3\x9e\xfe\xb9\x19\x0e\xf9\xee\xf5\xdd\x4e\x6a\xef\x5e\xb5\x5f\xd5\xee\x45\xae\x78\xfe\x04\xa0\xdf\xa4\xad\x9d\x8b\x3b\xf9\x4a\xa4\xa5\xfd\x6a\x6f\xd3\xf4\xda\x6d\x8a\x5b\xf2\x66\xd2\xaf\x5f\x58\x7c\xbf\xb0\xf8\xfe\xa2\x58\x7c\xb3\x75\x35\x4b\xe7\xb5\x57\x7b\x07\x0d\xff\x44\x7c\xc2\xd4\x81\x19\x40\x25\x28\xe5\x16\x29\x25\x1f\x48\xa8\x49\xcf\x48\xe0\x9c\x99\x11\xea\x4f\x1c\x0d\x2f\xe6\xa0\xd3\xb6\xd6\x1e\xac\x19\x57\x1f\xf4\x1b\xa2\x22\x52\x27\x15\x95\x5a\x9e\xe3\xb0\x72\x1b\x8e\x0b\xb7\xe1\xb8\x0c\x43\xc6\xec\x58\xb1\x4e\xf1\x04\xbe\xa1\xa7\xc4\x2b\xc0\x2e\xeb\xaf\xc3\x9e\x0d\x67\x86\x33\xe1\x8c\x75\x03\xd6\x23\x7f\x15\x81\xfc\xdd\xeb\x44\xae\xbf\x80\xa4\x5f\x40\xd2\x5f\x38\x48\x6a\xdd\x59\x63\xf2\x4e\xbb\xe9\xa8\xe8\x8e\x97\x59\x40\xbd\x1a\x70\x35\xc4\x40\xcf\x89\x75\x2e\x30\xc4\xf3\x0c\xbe\xd0\xcf\x01\xad\x90\x8a\x46\x14\x58\xf5\x7f\x2a\x63\x80\x29\xd6\x47\xc1\x08\xa0\x45\x95\x47\x40\xef\x31\x48\x84\x51\x4c\x2c\x2b\x33\xd5\x54\x6c\x2b\x27\x11\x34\x30\x00\x2b\x77\x34\xb5\x33\xdc\x73\x6b\x2b\x65\x75\xa7\x9f\xb5\x56\x54\xf9\x7a\x13\x1d\x7f\x7e\x6f\xc9\x11\x89\xa9\xaf\x36\x4f\x1d\xcf\xad\x8e\xd5\x92\x2a\xe5\x17\x53\x70\x35\xa3\xb9\x35\x9e\x01\xb7\xcc\x74\x53\xa0\x7b\x9b\xbf\x93\x7f\xfa\x1c\xf6\x0e\x15\x28\x29\x94\xae\x19\x25\x7a\x0d\xa0\xa7\xb1\x0c\x65\xdd\x20\x74\x5f\x66\xf5\x9d\x5d\x55\xb0\xee\x7a\xc5\x7c\x2f\x92\x63\x62\x08\x71\x40\x41\xcd\x13\x42\x96\xd0\x50\xb3\x2f\x6e\xa6\x8f\xa4\x98\x1b\x37\xd3\x3c\x32\xdc\x21\xbf\xe4\xc4\xc6\x28\x56\x93\x5a\xd0\xcd\x38\x5a\xdc\x64\xfd\x6c\x3a\x39\x1f\xaa\x5b\x6e\x2b\x65\x33\xf0\xcc\xf5\xca\x5f\xd0\xff\x50\x38\xca\x94\x83\xdf\xda\x6b\xbe\x96\xcb\xc4\x67\xb6\x57\xe3\x87\x59\x31\xa1\x7a\xf5\x4c\xa8\x9e\x05\x16\x6e\x54\xdf\xf5\xfc\x9d\x2a\x9c\xf4\xee\x2e\x7d\x06\xd7\xa7\x46\xbd\xa4\xe0\x39\x7c\xa6\xee\x95\xb9\x98\xd1\x3a\x39\x40\xf7\x13\x65\x9f\x27\x50\x05\x40\x50\xb8\x9d\xd9\x99\x49\x9d\x27\x13\x5b\x16\x45\x3a\x3d\xe4\x07\xc7\x52\xd5\xad\x28\xf1\xa2\x36\xf1\x7c\xc1\x93\x8b\xee\x48\x0a\x77\x44\x60\x1b\xb6\xb2\xa3\x8c\x71\x8d\xa3\x8c\x54\x8e\xd1\x51\x46\xb8\x93\x62\xdf\x22\xf8\x29\xf7\x0d\x46\x89\x1d\x41\x4e\xbc\x2f\x62\x74\x4b\x69\xba\x1a\x97\xc6\x2f\x12\x68\x27\xcc\xdd\x00\x84\x2b\x09\xb4\x93\xb8\x91\xcc\x76\x92\x3d\x11\x69\x8b\x17\x73\x3e\x77\xf8\xd5\x1e\x5b\x53\xcc\x50\xe1\xa7\xfd\x41\x46\x32\x7d\x6d\x18\xca\x48\xa9\x30\x75\x48\x40\x2d\x22\xdb\x4a\x67\x61\x21\x76\x0a\x2f\xa0\xaf\x85\xa0\x70\x05\x53\xe4\xe9\x3a\xd2\x5a\x59\xfb\xaa\x18\x03\xae\x7e\xe5\xd9\x0e\xc8\xc1\xb5\x46\x27\xad\xea\x91\xd6\x7c\xd6\xa2\x8f\x7f\xe6\xfa\x7a\x74\x0d\xa0\x9e\x1d\x40\xbb\x73\x16\xa1\x64\xea\x98\x01\x88\xbb\xd2\x8e\xfb\x76\xf6\x04\x3a\xda\x1d\x2a\xbd\x9f\xc9\xe4\x11\xe2\x0f\x4a\x45\x47\xe3\xe5\x93\xc9\x27\x71\x8a\x44\xfe\x4b\xfc\xb3\xca\xea\x84\xcf\xe9\xa7\x53\xb1\x28\x22\x24\x92\xec\x4f\xf6\x9d\xc4\x05\x6c\xcf\x46\x8e\xf7\xbb\x23\x67\xfe\x68\x32\x69\xa0\xdd\x0a\xda\x0b\x47\x80\x9f\x9e\xb6\x5e\x6e\x3e\x5a\xdf\x5f\x7f\xf9\xb6\xd6\x96\xc8\x9f\x63\xd5\xf0\x39\xdd\x49\x9c\x1b\xd2\x6d\x9e\x0b\x72\x7d\x5b\xc0\xf0\x7a\x3e\x66\x47\x7b\x1b\x45\xf5\x9c\xc1\xb5\xab\x89\x9b\x4f\x00\x5b\xb0\x60\x7a\x11\xf5\xd8\x24\x09\x33\x2a\x1f\x96\x68\x90\xd3\x70\xbd\x81\x03\x5d\x03\x62\x27\x08\xfa\x29\x54\x4f\x02\x27\xee\x52\x2f\xd7\xb6\x06\x2a\xab\xa8\x60\x8d\x88\x6c\x02\x4b\x73\x38\x99\x6c\xa0\x72\x36\x8c\xfe\x82\xa7\xf7\xa3\x1c\xce\x70\xe4\x4f\x7b\x92\x3c\x9f\x29\xc5\x77\x80\x77\xe3\x28\xd2\x0e\xb3\x49\x27\xee\x15\x5c\x05\xf0\xe2\xb5\x11\x54\xd9\xd7\xc1\x2a\xcc\xf4\xaa\x52\x79\x84\x0b\x89\xd7\x05\x75\xb7\xd1\x8f\xe5\xea\x70\x58\xd5\x75\xfd\xd8\x9a\x52\x2d\x14\xff\x48\xfb\x5c\x5b\xbd\xc1\x3a\x7f\xd4\xae\x44\x76\xf6\x00\x31\xed\xf7\xcb\xd5\xc1\x06\x33\x1b\x6b\x9d\x24\x76\x08\x0e\x0a\xd5\xb8\xa6\x12\xb2\x98\x53\x18\xa4\x7e\x47\x21\xf3\x94\x6e\x5e\x4d\xe5\xd0\xd9\xc2\x40\xa8\x8f\xa6\x1f\x68\xc9\xff\x11\x51\x2e\xc0\xf6\x49\x55\x99\xcc\xbc\xeb\x54\xf8\x37\x5b\xc6\xe5\x49\xb1\xe9\xa9\xde\x3e\x88\x98\x42\x2c\xe2\x95\x6d\x1c\x06\x23\x84\xa3\xc2\xfe\xbe\x95\xce\xac\xbd\xb5\x5f\x77\x33\xaf\x30\xf8\x9d\x6c\xaf\x33\x70\xc2\x42\x1e\x71\x5b\x91\x81\xd8\x25\xd8\x3f\x55\xb0\x46\xae\xb7\xd8\xf4\x4b\xa3\xd6\xaf\x5a\xc6\xde\x1c\x7b\x64\xf9\x12\x70\x48\x0d\x73\xa6\xd3\x11\xee\xe9\xc7\xb2\x9b\x12\x03\xdb\x61\x93\x1f\x77\x1b\xbf\x6e\x34\x43\x2f\xbc\xc6\xed\xc8\xb4\xaa\x56\xbb\xc6\x73\x88\x13\xba\x5e\xc2\xd6\x91\xe1\x35\xfe\x47\xf2\x32\x95\x1a\x67\x79\x1d\xd9\x56\x77\xcb\x4a\x1b\x8e\x2a\x74\xfe\xa2\x8b\x41\x4a\xc8\xab\x32\xd0\xab\x9e\x33\x22\x56\x88\xf6\x43\x32\x77\xe6\x1b\x13\x42\x1b\x42\xc0\xd5\x12\xa6\x00\x1a\x34\xa4\x50\xfe\xaf\x80\x52\x9a\x6f\x1b\x3f\xa9\xab\xa8\x18\xeb\x65\xad\x38\xa2\x54\x31\x96\x2b\x6a\xf8\x16\x20\x5b\xd5\xa1\xf5\x9b\x88\xeb\x81\x85\xc6\xf2\xf0\x9b\x4f\xef\xfc\x1c\x6b\xdc\x7a\x48\x7e\x02\xdd\x69\x57\xf5\x02\x4d\x4c\xec\x17\x5b\xdd\xfa\xc9\x22\x51\xa9\x91\x90\x6a\xb1\xb4\xa7\xe6\xc3\x8c\x83\xba\x43\xe3\xa0\x54\x71\x1c\xdc\xeb\x4c\xe7\xd5\x0a\xa0\x6b\xf0\x78\x18\x94\xce\x23\x82\x2f\x3a\x46\xca\xa5\x14\x74\x00\x60\x3e\xb4\xa3\x3f\x14\xac\xba\x66\x82\x1b\xc5\x4c\x39\xe5\x8a\x62\x15\x56\x2d\xc2\x43\x87\xb0\x14\x26\x3b\x86\x25\x07\x92\x1f\x96\xb8\x4f\xda\xb1\x0b\x0b\x78\xdc\xab\xa6\x41\x70\xc9\xa8\xd0\x6c\x1f\x95\xab\x07\x44\x57\x73\x17\x13\x2f\xd5\x22\xcf\xb1\xcf\x8f\x34\xb7\xd3\x6c\xcd\xbd\x80\xa9\x9c\x4b\xc7\xb0\x1b\x2e\x00\xc8\x13\xda\xc1\x76\xba\xca\xe4\x16\x32\xad\xcc\x21\x62\x70\xc6\x5b\x26\xc2\x7c\x8a\xa9\x96\xc2\x59\xc5\xd3\xca\x3d\xf7\xd1\x02\x13\xad\x80\x3a\x0a\xff\x82\x6b\xf4\x54\x01\x9b\xc9\x04\x6e\xd9\x21\x8d\x95\x2d\xda\xc8\x8f\xca\xa9\x36\x6a\x83\x27\x74\xda\x65\xe5\x3d\x96\xbe\x9d\xf7\x10\x1e\x4d\xde\x4e\x4f\x07\xf0\x73\xd0\x7c\xbb\xc6\x1e\xec\x57\xda\xec\xcb\x81\x15\x12\x43\x71\x2c\x06\xe2\x10\x3d\x68\x8e\xe5\xd1\x74\xfb\x31\xc8\xde\x2b\x64\x87\xb3\x84\xa0\x1f\x4b\xf1\xa0\x2e\xe8\x52\x3f\x23\x18\x6f\x1d\x6c\x96\x82\x7f\x44\x7b\x9e\xce\xaa\xbc\xa0\xac\xfb\x80\x7d\xb2\xf7\x11\xdd\xdb\x45\x6d\x37\xeb\x76\xce\x48\xfd\xde\xb9\x10\xa9\xd8\xcf\x7d\x9b\xe4\xa8\x58\x30\x99\x5c\xd8\x4a\xe9\xdd\xe7\x6c\x63\xf9\x11\x60\xc3\x85\xf2\xe4\x70\x06\x5b\x1f\x6a\x18\x43\x6f\x0f\x0b\x75\xd8\x79\x95\x15\x22\x0b\x9e\xe1\xa8\x45\x42\x5b\xdb\x79\xbe\x31\xbc\x13\x0a\x25\x3a\xd2\xe4\xdf\xb1\xa2\xec\x0e\xaf\x5c\xfa\x07\x50\x6c\x5c\x34\x0d\x1b\x38\xf3\x1f\x5b\xe6\xb2\x16\xea\x22\x47\x80\xe2\x0f\xe1\xb6\xef\x5f\xcc\x25\xfc\x09\xc0\xc9\xf3\x9c\xc7\xa2\x8d\x0c\x70\x23\x5b\x07\x13\x9d\x68\xad\x22\x26\x84\xb7\x39\xa3\x56\x51\x61\xf8\x3a\xf7\x2a\x1b\x31\x14\xf4\xf5\x31\x4e\x01\x8f\xf7\x23\x20\x67\x09\x99\x43\x14\xa0\x12\xa2\x23\x78\x69\xf2\x79\x7e\x0e\x60\x2e\x88\x02\x38\x57\x35\x2f\x1d\xdd\x50\x11\x06\xe0\x35\x6b\x06\x4b\x3c\xc1\xc2\xb5\xab\x92\x45\x2c\xc3\x00\x8a\xaa\x4d\x91\xa2\x31\x01\xeb\x29\x7a\xb4\x9f\x85\x9a\x20\xf4\x3b\x8e\x4f\x83\xea\x20\xea\xde\xdf\x6c\x1c\x6d\x32\x07\xd2\x59\x6a\x2e\x9a\xc4\xb2\x10\x34\x0c\xea\x6a\xb6\x5e\x6e\x56\xa4\x98\x12\x35\xac\x0c\x0d\x09\x2c\x17\x34\x01\xba\x84\x12\xd3\x98\x32\x25\x40\x8a\x99\x65\x44\x2d\x59\x93\x59\xd3\x1b\x86\xa7\xe5\x8c\x53\xcc\xb7\x4e\xcd\x21\x28\x16\x98\x62\xa7\xa5\xe1\x97\x9d\x79\x9a\x41\x96\x02\x6e\x76\xd6\xa9\x96\x57\x7a\x72\xae\xb7\xad\x2a\xa1\x63\x5d\x74\x87\xca\x83\xf0\x7c\xe7\x34\x47\xed\xd0\x84\x5f\xf7\x16\x10\x24\xd4\x0c\xe3\xeb\x65\x32\xc1\x10\xf6\xd4\x35\x42\x33\x00\x6f\x0a\xcf\xe1\xb8\x78\x3b\x07\x7b\x76\x38\x2d\x23\xba\x5f\xd3\x02\xcf\x0a\xcb\xc2\xb3\x59\x16\x6b\xd3\x59\x20\x6b\x53\xcc\xf2\x6c\xd6\xe8\x6c\x9e\x68\x5b\x57\xf5\x71\x76\x74\x24\x3d\x9d\xf2\xe5\x8d\x22\xc1\x94\x23\x5f\x40\xb9\x72\x40\x10\xc5\xb2\x2c\x1e\x53\x3c\xb8\x7c\xf0\xeb\x3d\x8a\x7f\xac\x30\xe9\x96\x2c\xa6\xd4\xb0\xc4\x7a\xca\x0c\x03\x2c\xe7\xc7\x29\x77\x94\x39\xd7\xac\x86\x12\xd0\xf6\xd1\x08\x4c\x2d\x9a\x40\xbd\x85\xb3\x7e\xc5\x7e\x10\x2c\x76\xfa\x68\x9a\xcb\x95\xc1\x74\xd1\xdf\xd1\x67\x1a\x3a\xf7\x99\x65\x3f\xdd\x3c\xe8\x94\x33\x68\x5b\xdd\xf4\xce\xc6\x71\x88\xd3\xff\x10\xb0\xb0\x34\x48\x34\xa0\x81\x9c\xc7\x9c\x53\x13\xbd\xe9\x9d\xa7\x7e\x7a\xa4\x2b\x84\xef\x87\x95\xef\x8c\xc3\x5a\x59\x2e\xca\x59\xb6\x18\x58\x5b\x59\xf6\xcb\x59\xb6\x89\x1a\xb5\x72\x1c\x70\x8e\x6d\xdb\xae\x19\x5e\xaf\xab\x90\x76\xb9\xed\x7f\x8a\xb1\x01\x28\xb2\x9e\x8e\x5f\x03\xd9\xce\x55\x08\xde\xb4\xfc\xe1\x8c\x3f\xe4\x70\x1e\xde\xad\x55\xad\x5d\xb7\xca\x26\x88\x62\x9b\xdf\xe4\x3d\x79\x51\x6b\xbb\xb8\xc9\x6f\xd9\xd3\xa5\x2b\x5e\x17\xf5\x2b\x36\xf8\x31\x1d\x8f\x88\xa9\x98\x57\xf6\xaa\xea\x7e\xe7\x91\x3c\xea\x1e\xa3\x0f\x0e\xf1\x09\x52\xa7\xb4\x39\x2d\x53\x8b\x5e\xc1\x13\x38\x94\x46\x81\x4e\x2f\x48\xa1\xa8\x3b\xdd\xbc\x4d\xb7\xe8\xb5\x7f\x2b\x4c\x37\xbd\xf6\xd7\xa2\xea\xc4\xa0\x4e\xc2\x69\x19\xc7\x59\x9a\x15\xcb\x77\x45\x65\xa5\xbc\x65\x8a\xbc\x6c\xcd\xb3\xb7\x4c\x3d\x98\x61\xf2\x25\x6e\xb2\x43\xbd\x65\xea\xec\xec\x0d\xe0\xdd\xa5\x4c\xe5\xe5\xf7\xee\xd1\x30\xa6\xec\x6d\xef\xde\xb2\x98\xb9\xb3\xbd\x7b\x77\xc5\xcc\x7d\xed\xdd\xbb\x27\x66\xed\x6a\xef\x1e\xa9\x4a\x95\x97\xdf\xbb\xf7\xb5\xd0\xab\xe7\xdd\xab\xe7\x1e\x7f\xbe\xad\xf7\x0c\x7f\x12\x77\x3f\xdf\x2f\x32\xf1\xf4\x80\xb4\xfc\x14\xc5\x67\x51\x2e\x04\x32\xac\xdf\x64\x3a\x0f\x3a\x71\x35\x0d\x1f\xec\x24\x7b\x0e\x1a\x71\x02\xa9\x54\x60\x50\x10\x46\xba\xb0\xd0\x43\x22\x3a\x6c\x1d\xc3\x3c\xf8\x87\x28\xf8\x2f\x1a\x4a\x30\x52\xc3\x82\x14\x8c\xd4\x63\xa4\x18\x1a\x60\x93\xbf\x3b\xe3\xf3\x29\x6a\x21\x23\xee\xb5\xc5\x5a\xc8\x5d\xcb\x54\x3e\xe2\x1e\x42\xf1\x83\xcd\x63\x26\x6a\x1b\xfd\x4a\xbd\x45\xef\x4d\xe6\xea\xc8\x1d\x08\xb4\x58\xb4\xcc\x5d\x0a\x0a\xca\x03\xa4\x0e\x8e\x97\x8a\xc1\xbd\x72\x85\x05\x64\x69\x9b\x38\x0f\xc8\x94\x13\xd6\x47\x41\x01\x02\xa5\x1c\x76\x8f\x5a\x55\x27\x2e\x4e\xe8\x00\x02\xe1\x61\x86\x91\xc9\x50\x70\xc5\x62\xe5\x18\x98\x1c\xfa\xe0\xaa\x8f\x47\x05\xdf\x29\xf8\xce\x0e\x2b\x16\x19\xcd\xdf\x85\x05\xdf\x89\x2c\x3d\x60\x7b\x45\xfc\x7c\x45\x76\xf6\xf4\x20\xd3\x3c\x86\x98\x76\x51\x99\x09\x1b\x2f\x75\x32\x49\xa1\xec\x48\xaa\x8d\xec\x1a\x74\x18\x02\xd3\xce\x2e\x2e\xad\x5b\xf3\x26\xc2\xe6\xba\x4b\x75\x98\x87\x3c\xa5\x1d\x9a\xde\x29\xf8\xc0\x51\xd7\x71\x21\x43\xd1\x93\x8d\xba\x97\x0b\x39\xac\x6b\xe0\xa8\x00\xd0\x67\x79\xec\x9b\xd1\x0b\xef\x6e\x5b\xcc\xea\x83\x77\xb7\x5c\x3c\x87\xbc\x77\xa7\x00\x88\x99\x9e\x66\xca\xe7\xff\x3a\xc3\x5a\xeb\xfc\x1b\x04\x2f\x74\x72\xf7\x1f\x80\x6a\x19\x1e\xb6\x72\x03\x32\x52\x7c\x91\x8a\xdb\xf7\xcb\x73\x6d\x10\x3c\x82\x43\xfd\x9e\x83\xe7\x4c\x26\xfd\xb8\x47\xa2\xfc\x96\x4e\xa8\xf3\xa5\x64\x00\xcf\x83\x41\x26\x2e\xec\x92\x1f\x6e\x58\x12\x43\x42\xfd\xcc\x8e\x64\x4a\xa6\xc2\x7f\xa8\x0b\x8e\x7b\xd7\xd9\x19\x47\x2d\x7b\xbb\x5c\xb7\xa3\xa3\xd6\xf3\x30\xfa\x54\xc9\x85\x2f\xe9\x6b\x61\x6f\x5d\xbb\xfb\x31\x4a\xb1\xf2\x85\x30\xe3\x18\x40\xae\xda\xda\xf2\x5a\x98\xa4\x52\xf2\xe1\xfa\x7c\xb9\x02\x9b\xaa\x4e\xe7\x2e\x95\x86\xcf\xf6\x45\x7d\x0d\x82\x0a\x99\x8b\xf7\xf6\xf5\x08\x2b\x8e\xb9\x70\x93\x5f\x8f\xc0\x46\xad\xe2\xdd\x7e\x2d\x3e\x1b\xb5\x5e\x07\x69\x36\x2d\xbb\xfd\x8d\x32\xd7\x63\x3f\x37\xc6\xe2\xa1\x7b\xea\x30\xc0\x71\x98\x56\xba\x26\x8b\x3d\x7f\x65\x84\x17\x76\x12\xe4\x39\xb4\xfa\x9f\x3f\x9b\x19\x51\x5b\x82\x6d\x72\x48\x30\x9a\xdf\x34\x05\xd0\x69\x7f\x30\xd9\xaa\xdb\xbe\x98\xdb\xfe\x6e\x0a\xd5\xec\xef\x62\xa9\x42\x86\xbc\x4b\x85\x6d\x5e\xea\x95\xfa\x56\xec\x7f\x15\xd1\xbc\x19\x31\xa2\x2b\xa9\xe4\xe6\xe9\x4e\xc6\xaa\x1e\x48\xe8\xd7\x7c\x99\x94\xb0\x75\x6b\xba\xbd\xf6\xfd\x2a\x02\x4e\x73\xee\x2d\x7f\xf9\x39\x78\xf4\xec\xdd\xe0\x2d\xdf\xff\xbc\x7b\x8c\x80\x8e\x77\x77\xf9\x0f\xb9\xde\xea\x20\x8a\x32\x32\x98\x06\x41\x50\xdb\xb2\x3c\xb5\xde\xdd\xdf\xde\x98\x50\xf8\x53\x53\x04\x53\x00\x81\x77\x8f\x86\x95\xef\x0b\xef\x1e\xfa\xc5\xb8\x77\x9d\x55\x7d\xad\x05\xb2\xf2\x92\x33\x99\xc4\x55\x8c\xb6\xd6\x22\x99\x4a\x4f\x26\x45\xbf\xda\x14\x7f\xb5\x15\x9c\xa2\x50\x30\xd1\x66\xc8\x39\xde\x56\xf2\xf1\x61\xfb\x02\xb8\xf7\x79\x76\xd3\xc8\x64\x4b\x95\x04\xc6\xd1\x1a\x24\x4d\xd9\xd6\x1a\x04\xcc\x64\x1f\x55\x19\xbd\x88\x93\x7b\x19\x0a\x2c\xaa\x5e\xd2\xd1\xdf\x1f\x11\xcd\x23\xd4\xc9\x28\x0c\x5b\xf3\x91\xaa\x35\x6a\x67\xe3\x65\x17\xf3\xdd\xf9\x25\xcf\x19\x19\x09\x19\x7a\xcb\xcc\x58\x90\x67\x11\x11\x2a\x9a\xad\xab\xab\xf7\x3b\x3e\x33\xdb\x61\x90\x93\x49\x8a\xae\x54\x5c\x46\x57\x7c\xa5\x78\x39\x8b\x8d\xa3\x55\xc2\x73\xa0\xdc\x93\x24\xe4\x01\xba\x69\x24\x2f\x2b\xbc\xf5\x02\x4f\xb8\xa7\x31\x6e\x01\xfd\x11\xc3\xc9\xc4\x51\xd8\x15\x14\xa3\xa8\x78\xba\x54\x77\xca\x7b\xa7\x01\x94\xdd\x51\x8f\x5a\x68\x88\x18\x87\xaa\x11\x34\x3f\xcb\x60\xa6\x29\xb7\xd3\x88\xa3\x42\x3e\x44\xca\xe7\x97\x88\x75\x57\xe5\x9a\x17\x7b\x58\x23\x59\xb2\x04\x34\x28\xa0\x03\x6a\x01\x4d\xe9\x7b\x26\xf6\xb0\x1e\x04\x57\x5e\x3b\x8e\x9a\x4f\x33\x86\x62\xe5\xae\x1f\x0a\x4a\x6a\x71\x26\x0b\x5d\xf7\xd5\x66\xd5\x91\x8d\xf4\x89\x46\x62\x18\x68\x06\x23\x93\xae\x14\x52\x5e\x77\x2a\xe5\xf4\xb6\x2a\xbf\xd7\xbc\xf3\x66\xf9\x43\x4a\xe1\xbe\x9a\x28\x53\x47\x2d\x83\x51\x51\xce\x41\xfd\xdb\x7c\x25\xc6\x3a\xd6\xd2\xf5\x4c\xfd\x7e\xd0\x8b\xfb\xc1\x9b\xad\x8d\x4a\x1f\xd0\x96\xb5\x05\xd4\x6b\x08\x33\xf4\xeb\x86\xbb\xd3\xde\x9b\x4c\xc8\x41\xbd\xf6\x47\x5c\xad\xad\xf1\xc0\x86\xac\x2b\x8d\x82\xff\x1d\xad\x5b\x57\xbc\xef\xae\x73\x0f\x74\xef\x3a\x93\xc9\x22\x40\xb1\xc1\x46\x6f\x3a\xd8\x48\x67\x81\x8d\x5e\x05\x6c\x60\xc5\x79\xf4\x71\x72\xed\x87\xe4\x7d\xcc\x07\xdb\x80\xc7\x99\xa7\xda\xaf\x9c\x6a\x25\x01\x45\x7d\x9c\xeb\x4e\x75\x6a\x4e\xf5\xf8\xa7\x9c\x68\xd8\x26\x29\xdb\x4f\x87\x33\xce\xb3\x95\x0b\x81\xd0\xcd\x4e\x73\x0a\x5b\xee\x66\xa7\x39\xad\x9c\xe6\x69\x03\xa8\x3d\xca\x53\xc6\x50\x3a\xc8\xe5\x31\xd4\x1e\xe3\x52\x5c\x32\xfc\xae\x62\xb7\xb2\x4c\xf7\x4a\x34\x1a\xe4\x87\x20\xbf\x90\x04\xad\x36\x1c\x7d\xb7\xfe\x90\x97\xaa\x54\x59\x6a\x6b\xc5\x9a\x14\x3c\x50\x27\xd8\xa7\xe3\xfa\x87\x9c\xd5\x6b\xe0\xc5\x75\x87\xb6\x88\xf0\x94\xce\x6d\xef\xa7\x9d\xdb\x9b\x99\x85\xda\xd4\x87\x45\x1a\x85\x95\xc3\x12\xc3\xa1\x9e\xb2\x8e\x43\x43\x6e\xcd\x5c\x9b\x0a\xd0\xd5\x00\x34\xac\x9d\xfe\xb2\x74\x79\xe6\x0c\x96\x30\xc2\xd2\x0c\xc6\xb5\x33\x58\x87\x67\xe2\xc4\x7d\x46\xe8\x46\x80\xf8\x4e\x49\x8b\xf0\x38\xee\x87\x83\x8b\xaa\x5e\x63\xc3\xfd\x25\x04\xdb\x5f\x4c\xa0\x06\x9b\x05\x35\x35\x14\x5b\x6d\x10\x36\x19\xd4\x84\x28\x28\xee\xc2\xeb\xfc\x78\xf9\x96\x51\xc4\x8c\xb8\x01\x5c\xe6\xf6\x83\x22\xa1\x32\x3d\x16\x80\x72\x89\x9d\x5a\xde\x30\xf1\x34\xca\x44\xd8\xaf\xd4\xc1\x2a\xbd\x85\x23\x56\x08\x96\x99\x16\x99\x6b\x55\xc6\xd9\x2f\xa6\x72\x7f\x2a\x53\xb9\xa9\xfb\xd8\xbf\x16\xbd\x49\x2b\x10\x7b\x3c\x7d\xef\x27\xc5\xbd\xaf\x6e\x4d\x0c\x23\x01\x18\x11\xbd\x1a\xaa\x7b\x9f\x70\x24\xdb\x86\x49\x03\x4d\x9a\x73\xc7\x32\x43\x37\x07\x46\x6b\x58\x37\x10\xa2\x57\x37\xfd\x7c\xbb\x6c\xf2\x54\xa8\xb2\xce\x00\x56\xad\xb0\xb4\x3b\xab\xde\xe5\x75\xc1\xa6\x02\xc0\xbb\xa6\x88\x88\xaa\xdd\x91\xde\x35\x1a\x3b\x35\xce\x60\xea\x10\x54\x01\x7b\x0b\x75\xe7\x0b\x53\xa1\x37\x5a\xb2\x12\x75\x9a\xcd\xc8\x2d\x7e\x85\x2d\x67\x89\x8a\xad\xf0\x21\x15\xcc\x72\xaa\x51\x57\xde\x92\x96\xda\xe4\x56\x43\x55\x34\xf0\xfa\x6a\xca\xfd\xbf\x16\x4f\x34\xed\xb1\x8f\xd5\x29\xf5\xdb\x78\x9b\xa3\xf7\x50\xfd\xf6\x50\xdf\xec\xb5\x71\x7c\x85\xc7\xe5\x63\x53\x0e\x5c\xab\xcd\x29\xc7\x4d\xc5\x25\x2f\x5c\xb7\xaa\x70\x41\xdf\x9f\x74\x40\xc9\x0a\x20\x8a\x2d\xe5\x5f\xbb\xaa\x9d\x9a\x7a\x17\xdb\x7b\xda\xbd\x72\xb9\xc3\x06\x5d\x34\xf3\x13\x8f\xa6\xd9\xfa\x99\xd9\x21\xb5\xe5\xcf\x9f\x1b\x62\x55\x88\x9f\x70\xf7\xcc\x1e\xda\xcd\x6f\xa5\xc6\x03\x9b\x3d\x86\xa8\x54\x35\x22\xc3\xf8\xf3\x71\xd2\xd9\xc2\x9a\xeb\x3c\x00\x57\x65\xe5\x35\xe1\x3b\x02\x72\x13\x16\x88\x80\x8d\x25\xd4\x45\x15\x3a\xc6\x32\x46\x68\x6c\x8c\xc2\xe1\x68\x06\x1c\xf2\x86\x51\x3a\x9b\xd8\xde\xb2\x8b\x0c\xe4\xb2\x6c\xaa\xca\x05\xc5\x41\x7c\x86\xc0\x5f\x73\xaa\x22\xe6\x36\xc7\x49\x0b\x32\x26\xab\x87\xb0\xd4\x1d\x1d\xf3\x81\x18\x61\x3a\xe6\x43\x63\x35\xea\x27\x48\x03\x2f\xb7\x1a\xee\xc2\xc2\xb4\xaf\xf7\x5a\x4b\x0d\x77\x32\x29\x7f\x7e\x11\x1f\x84\xc3\x60\x6e\xdb\x1f\xc0\xbc\x73\x86\xf9\x42\x86\x35\xb8\xaa\x8f\x83\xba\x2f\xec\x23\x3f\x9d\x7b\x75\x14\x47\x90\xa1\x5b\xa4\xb4\x16\x16\x1a\x86\x7c\xc3\xab\xb3\xf8\xd5\x03\x60\x5f\x71\x00\x7c\xef\x33\xe4\xa2\xac\x1d\xa0\x98\xaa\xf5\xf8\x44\x41\x24\xab\xc1\xc2\x41\x40\x08\x46\xd0\x57\x70\x40\x59\x87\x8f\x23\xbe\xc0\xfb\x0d\xb3\xfa\x5c\x1c\x61\x6d\xde\xd1\x42\x95\xb6\x46\x7d\xd1\x1e\x2e\x14\x31\x07\x9d\xf4\x65\xbb\xe3\x3f\x30\x66\xd3\xfa\x9e\xf0\x11\x21\x89\xa4\x79\xbf\xe3\xef\x89\xb0\x10\x79\x5d\x35\x1e\xb9\x6e\x6e\xdd\x07\x48\x4d\xfa\xc0\x44\xbd\x4e\xa1\x8e\x78\x07\x0d\xf8\xf6\x64\xc4\xbf\x06\x47\x55\xb1\xe6\xbf\xac\x11\x74\xe6\x63\x61\x11\x18\x9c\x39\x2d\xee\xa0\xb4\xf7\x25\xfa\xa1\xff\xb2\x86\xc5\x6d\x91\x85\x26\x7c\xa1\x21\x08\xef\x50\x64\xc5\xc2\x71\xb8\x34\xb9\xbc\x44\xd0\x67\x2f\xbc\xe2\x96\x38\xb3\xf7\x25\xb1\xf7\xf3\xca\xbc\x2f\x91\xcc\xfa\xb2\x86\x51\x6d\xb5\x3d\x56\xfa\x59\xa1\xbc\xec\x07\xff\x3f\x77\x6f\xdf\xd5\x36\x92\xed\x8d\xfe\xff\x7c\x0a\xd0\x3d\x8b\x91\x0e\x15\x07\xa7\xbb\x93\x8e\x1c\x85\x45\x80\x4c\x73\x27\x04\x2e\x90\xe9\xf3\x5c\x86\x43\x0b\x5b\x06\x4d\x6c\xc9\x2d\xd9\x24\x0c\xf8\xbb\xdf\xfd\x52\xaf\x52\xc9\x40\xcf\x3c\xeb\xcc\xba\x7f\x80\xa5\xaa\x52\xbd\xd7\xae\x5d\xbb\xf6\xfe\xed\x49\x3e\xcd\x51\x47\x32\xd8\x08\xc4\x88\xd4\x26\x7f\x12\xe4\x4e\xf1\x13\x46\xa0\x1e\x95\xf6\xb7\xc4\x21\xfd\xec\x87\xe5\x20\x67\x3f\x90\x7f\x45\x2a\xd7\x04\x9c\x34\x2c\x24\xfa\x25\x44\x99\x12\xc9\xd9\x50\xbb\x44\x16\xa6\x7c\xd4\xe8\x4c\x61\x41\xf5\x5f\x6e\x6d\xb3\x1c\x2a\x6e\xc6\x92\xc3\x7b\x98\x08\x7a\xe0\xd2\xf7\x25\x30\x09\x25\x37\xaa\x4e\x72\xf4\x70\xb9\x48\x68\x5d\xd6\x66\x71\x5d\x24\xb0\xa2\xac\x77\x78\x8d\x1b\xd1\x9b\x7d\xb4\x9b\xa0\x0f\x17\x51\x71\x5e\xf5\x58\x0a\x11\xd6\x11\xc4\x06\xc6\x62\x69\x98\x98\x28\xed\x1d\x74\x11\xa1\x30\xb5\x15\xb1\xd8\xec\xb3\x25\xb5\x9c\x8c\xe6\xb0\xd0\xd0\x2a\x1a\x46\x11\x9a\x06\xe7\xc5\x22\x1b\x14\xe7\x43\x98\x83\xed\x14\xdb\xe7\x17\xc8\x4b\x03\x61\x0d\x31\x49\xa4\x5e\xd0\xc3\x93\x66\x8b\x8b\xa5\x90\xe3\xc1\x45\xb6\x5c\x00\xe0\x01\x42\x99\x96\x2a\xc3\xee\x4c\x09\x29\x18\x92\x95\x58\xe4\xfb\x25\xd6\x3b\x38\xbf\xc0\x7b\x82\x2a\x2a\x91\x3f\x45\x7f\xa8\xb2\x50\xa7\x10\x65\x71\x64\x3a\x29\x4d\x82\x73\xfa\xf0\x7c\xeb\x02\x48\x17\x67\x72\x5e\x99\x6d\x72\xbb\x92\x5d\x84\x27\x04\x15\x1a\xc1\xd4\xae\x13\xca\xf8\xa0\x98\x87\xa9\xe8\x6f\x21\x7b\x1d\x04\x9b\xf5\x60\x3d\xaf\x3f\xa7\x9f\x61\x34\x36\x36\xd0\xb6\x25\xdd\xd8\x58\x24\xf4\x53\xbf\x4f\xb6\xe0\xff\x3b\xe8\x32\x33\x57\xb7\x43\xae\x30\xac\xe3\xc4\x5b\xd5\xb8\x04\x2a\xe1\x8d\x32\xcb\x5e\xf5\xe4\x5f\x80\x84\xf8\xfa\x71\xae\x56\xd2\xcb\xff\x0e\xcf\xff\x1b\xfd\x06\x5f\xfc\x67\xf4\x12\x7a\xe9\x65\xf8\xb7\x73\x15\xf0\xb7\x8b\xe8\xe5\x35\x7a\xe6\x84\x95\x9c\xa1\x41\x29\xb9\xc4\x7d\x6c\x3e\xa4\xe8\x53\x55\xcd\xe9\xf3\x8b\x01\xbe\x43\x23\x99\x15\xa4\x48\x4d\xc8\x16\x78\x3a\x63\x4c\x8f\x30\x85\x01\x92\xc5\x40\x3f\x2d\xde\x15\x3d\x5a\xc6\x83\x68\x73\x73\x21\x9e\x52\xa6\xe5\x4b\xf8\xfc\xe1\x6f\xe8\xd4\x38\x08\xa2\x08\xaf\x76\xac\x92\x95\x19\xbe\xae\x10\x8c\xf5\xe6\x5c\x8e\x67\xca\xab\x2a\xda\x84\x41\x8f\xdc\xb9\x18\xd6\xd2\x73\x87\x6d\x89\xde\x3a\xde\x06\x74\x31\xc5\x1e\x7f\xf8\x29\x30\xdb\x89\x66\x41\xe6\x72\xee\xc2\x34\x55\x6e\xf9\x2c\xa2\x92\xb4\x5d\xf4\x99\x48\xb4\x4e\x45\x5d\x4a\x72\x3c\x6d\x85\x47\xdb\xd6\x4b\x9c\x3b\x24\x8a\xba\x31\x09\x58\x41\xdd\xcd\x15\x22\xb6\xe5\x2f\x7d\x04\xbf\xf0\x81\x99\x8a\xbe\xaf\xac\x89\x6a\xbf\xc0\xf7\xe6\xa5\x4d\x18\x3d\x19\xb9\x29\xb6\x9b\x01\x71\xde\x08\x18\x18\x82\xdc\xea\xa2\xf9\xb6\x43\xc9\x69\x40\x80\x95\x43\x52\x00\xf3\xd7\xde\x4e\x8b\x48\xba\xaa\x57\x82\xe3\x81\xf2\x50\x2f\x29\x64\x8a\x4e\xea\x27\x89\xb5\x7e\xc2\xa1\x40\xa2\x05\x59\x0e\x60\x33\xef\x4d\xb3\x0a\xb8\xf0\x52\x4c\xf4\x72\x43\x39\xc1\x74\x06\x8c\x6b\x58\x46\x72\x5f\xe3\xbd\x29\xfe\xe9\x47\xdc\xc6\x3c\xd7\x23\x4f\xd9\xc6\xa8\x3f\x8f\x2b\x98\x3e\xdf\xff\x8c\x87\x33\x64\x01\xeb\xf8\x5e\xf9\x05\xee\x70\xa9\xbd\x89\x74\x0f\x3d\x4e\x8f\x60\x4a\xaf\x48\x14\x6c\x66\x38\xcf\x49\x1c\x0b\x6c\x6a\x47\x42\xf4\x16\x91\x1b\x27\xc5\x3e\x52\x82\x33\xf2\xc3\x62\x3c\x46\xc7\x20\x68\x92\x81\x56\x89\xd2\x4a\x1d\xc6\xc0\x16\xf7\xec\x01\x03\x28\x13\x1c\x9c\x1e\xe9\x34\x6a\xb5\x90\x21\x71\x80\xce\xd7\x5b\xc3\x0b\x0b\xa9\x39\x81\x30\x0c\xc1\xa2\xb2\xb4\x68\x2f\xad\xf3\xac\x90\x62\x78\x03\xa5\x92\xc1\xba\x4e\xa0\xd5\xed\x98\x79\x74\x21\x9d\x49\x02\xb9\xc2\x65\xbc\x62\xd1\xae\x95\x7a\x1e\xba\x13\x6b\xfe\x94\x89\x35\xb0\xb6\xa1\xe6\x75\xfe\xb6\xd5\xcf\xe1\x1c\x27\x1c\x0a\x88\x86\x68\xde\x1b\xb7\xa2\x32\x1a\xc1\x21\x8e\x20\x19\xb2\x18\xc2\xdf\x45\x9e\x5c\x3f\xe3\xbe\x26\x5a\x24\x64\xdb\x22\x21\xb1\xcd\xf1\x54\xaa\x8b\x18\xbd\xd5\xa0\x33\x59\x54\x4f\x3b\x18\xe7\x4e\x1d\xa0\x8f\x4e\xcb\xb3\x35\xea\x27\x4b\x62\xd1\x9c\xdc\xdb\x4e\xc2\x38\x90\x93\x18\x0f\x0d\x19\xc4\xc9\xd7\x6d\x1d\x4e\x82\x01\x98\xbc\x81\x49\x6a\x8d\x4e\x47\x21\xc8\x65\xd5\xcd\xa1\x83\x9d\x48\x0c\xf5\xf5\xd7\x60\xf8\x7e\x01\x43\xb7\xe0\xa1\x9b\x24\xf5\xf9\xe2\x62\x50\x25\x95\xe1\x20\xec\xe1\x98\x00\xbd\x10\x69\x64\x91\x03\x72\xdf\x59\x78\x69\x81\xe7\xca\x45\x6e\xfe\x67\x65\x8b\xed\x71\x24\x52\x5a\xe0\xd4\x94\x31\x59\x63\x69\x86\xe3\xbc\xb8\x40\x1d\x6c\xf8\x49\x08\x3a\x42\x6b\x3f\x43\x36\x4c\xc2\x3c\xd2\x59\x0d\x97\x33\xf7\x8e\xb1\x8e\x6e\x4d\xdd\xb9\x72\x88\x1b\xa3\x83\x6e\x94\x94\xfa\x73\xd0\xab\x68\x9e\x9c\xcf\x35\x4b\x08\x84\xb5\xad\xdb\xb2\xde\x70\x23\xcf\x38\x03\x8d\xbe\x42\x66\xc1\x68\xbe\x3b\x83\x8a\xee\x89\xa0\xbf\x90\x62\xcb\xfe\x2a\xdf\xe7\xd0\x5f\x79\x24\xb9\xbc\x0a\xbd\x30\xd5\x49\x06\xcc\xd4\x60\x8e\x1c\x15\xfe\xdb\x96\x9d\x13\xe2\x8b\xa8\x81\xd3\x5e\x6a\x52\x28\x0a\xc9\x23\x3b\x23\x44\xce\x9d\x1a\x77\x7f\x16\x69\xb1\xb8\x92\x4d\x64\x49\xd6\xd0\x2a\x84\xfd\x23\x39\x64\x16\x75\xd3\x78\x13\xf1\xb0\x15\x8f\x2f\x36\x18\xb1\x8c\x65\xb3\x92\x1f\xce\x2c\x4f\x90\x7c\x38\x40\xf7\x90\x9a\x6b\x3e\xaf\x68\x19\x6b\xdd\x6f\xd1\x1c\x00\x33\xf5\x72\x66\x9f\xf1\xe4\x32\x6f\x9e\x5c\xfc\x53\xaf\x84\xa9\x97\xcb\x9c\xe1\x45\xcf\xbd\x5c\x6a\x97\xbb\x6b\x8f\xc6\x8f\xf3\xaf\xbd\x27\xa3\x45\x82\x6b\x16\xc6\x68\x81\x67\x0b\xb5\xd5\xe2\x2b\x8a\x50\xed\xe1\x51\xac\x91\x33\x40\x92\x1a\x9d\x73\x27\xae\x71\x0a\xe2\xea\x5b\x5c\xa5\xda\xb8\xa4\x90\x36\xe2\x3c\x79\x73\xf3\xe4\xb9\xf6\x08\x9f\xb7\xbd\xde\x8f\xc9\x9b\x84\x85\x15\x87\x4a\x5b\x36\xb0\xa2\xca\xbe\x2b\x1c\x87\x42\x1d\xe2\x9f\xe1\x30\x70\x5c\x0e\x17\xf5\x67\x98\x8d\xca\x61\xe0\x63\x0e\x20\x25\xca\xfb\x62\x5e\x7e\xc4\x4f\x09\x76\x5f\x4a\xbf\xf7\x8e\x0e\x31\x27\x04\x14\xf0\x38\xae\x33\x25\xc5\xfd\x37\x74\x6a\x7f\x86\xe7\x3a\x25\xe2\x92\x22\x21\xe4\xe6\x53\xa5\xe5\x25\x27\xbd\xe9\x4e\x38\x8c\xb5\xe5\x79\xf3\xde\x6d\x56\x21\xda\xdf\xc6\x86\x3e\x7c\xe9\x30\x38\x0d\xc2\x31\xec\x5d\xd2\x7f\xe5\xd5\xab\x0b\x1d\x97\x1e\xc6\xcf\x87\x74\xfe\x81\x44\xc8\x24\x21\x00\xbc\x09\xfb\xfc\x70\x6d\x53\xa4\x2f\xaf\xb9\xf4\xe5\x75\x04\xd3\x68\x46\x14\x80\xf5\xf0\x4f\xe7\x69\x35\x8f\xe5\x8c\x39\xa3\xf9\x6b\xc7\x0c\xbc\x1f\xed\x17\x23\xef\x27\x10\xee\xff\x40\xfa\xe8\xf4\x7d\xc3\x51\xcb\x4e\xe4\x23\x5c\x09\x98\x1b\x34\x6d\xaf\xfc\x56\xa0\x45\x08\x2c\xcd\x5d\x24\x74\x49\xb2\xdf\x82\x3c\xf2\x35\x17\x3e\xfd\x32\x8b\x95\x50\x12\x28\xcd\x95\x26\x3f\x3a\xb3\x68\xe0\xa4\xc7\xa2\x54\x75\x75\x1a\xf8\x72\xdf\x4d\x76\x8c\x60\x8e\xb1\x09\x82\xd9\x5b\x67\xf4\xad\x09\xfb\x30\x59\x54\xb1\x82\x40\x1a\x48\xe3\x1f\x15\xd0\x5f\x3a\x20\x4b\xc6\x64\x68\x04\xa3\x9c\x4f\xba\x66\x5b\x06\xb3\x0d\xba\x2d\x55\xbc\x07\x3e\xb3\x59\xaa\xce\x6d\x68\x1c\x07\x12\x9d\x14\x43\x24\xa9\xdf\xb7\x73\xb2\xac\x89\x8f\xb7\xb1\xc3\x2a\xdc\xb7\xf2\xa4\x39\x88\x51\x9c\x76\x44\xd2\xa4\x40\xe7\x17\x0e\x74\xdd\x09\x24\x3c\x7e\x78\xc8\xa1\x83\xda\xa9\xa1\xc4\xa4\x55\xc2\xc6\xc6\x31\x7c\x33\x4c\x8e\x69\x09\x43\xed\x61\xfd\xc6\xc7\xc9\x14\x5f\x8f\x91\x6f\x1e\xc1\x06\xa4\xbc\x85\x5f\x5b\xa1\x39\x35\x09\x9b\x32\x8c\x26\xd4\xee\x64\x68\xa4\x23\xb3\x64\x81\x80\x1b\xf2\xd4\x3e\x23\x4f\xe0\x94\x66\xa6\x49\xf1\xa8\x97\x0e\x87\x8b\xe9\x62\x02\xb3\xee\xec\x5b\x79\x0c\x67\xf5\x6c\x4f\x02\x02\xc0\xd9\x6c\x12\x09\xab\x13\x27\xdd\x93\xca\xbf\x1c\x16\x61\x73\x26\xf1\x14\x61\xbe\x36\xeb\x7d\xbb\xc9\x87\x37\xda\x0e\x0d\x11\xb3\xb6\xb1\xb2\x71\x78\x80\x6c\xc9\xa1\xfd\xed\x59\xf6\x7d\x7e\x50\xcc\x16\xf3\x58\xed\x99\xd8\x12\x1b\x19\xe7\x70\x63\xe3\x80\x3f\xaf\x1a\xf3\x6a\x8d\x4d\x94\x75\x3b\x66\x7a\xb7\x3e\x66\x01\x8b\x5a\x55\x6e\x2b\x1e\x1e\x78\x15\xf1\x94\x29\xec\xd1\x51\xe5\x4e\x81\x65\x80\x53\x4d\x9d\x41\x4e\xe2\x58\x02\x42\x2c\xed\x52\x7d\x9d\x75\x9c\xd6\x66\xf9\xd3\x94\xf1\xf4\x91\x5e\x6e\xd4\x49\x40\xde\x72\xe8\xcc\x6d\xb9\xe7\x21\x28\xc7\xee\x4d\x5a\xe1\x3a\x0c\x65\x12\x3e\x9c\x3d\x4a\xa2\x4e\xb8\x8f\x64\xff\xad\xee\xa8\x71\x63\xd5\x90\x43\xf9\x64\x77\x7b\x42\xeb\x21\x9e\xd1\x4f\x73\xfa\xf3\xe9\xec\xce\x9a\xa5\x67\xbd\xab\x0c\x18\x87\x8c\xc6\x8f\x67\xac\x3a\x03\xf1\x7c\xcc\xc5\x23\xf3\xb0\x8c\x44\x49\x0c\x89\xb4\x24\x23\xfd\xb4\xdd\x92\x8e\xab\x73\x3c\x90\x8f\xac\x70\x94\x34\xa5\x74\x09\x63\x19\x71\xfb\xad\x95\x94\xe1\xf6\x47\xe0\x21\x50\x69\xc9\xdd\x0a\xc8\x18\x43\x9a\x6e\x9f\xde\x15\xf3\x9b\x6c\x9e\x0f\xed\x5e\xbd\xe5\x4c\xee\x1a\x49\xa8\x9d\x2a\x52\x1a\x6d\x03\xd1\x3c\x1a\x93\x85\xf6\xf9\x5b\xd1\xff\x41\xbc\x7a\x23\x7e\x78\x75\x21\xf6\x93\x57\xaf\xde\x8a\xef\xc9\xad\xb1\x9b\x02\x62\xd6\x2a\x43\xdf\xc4\x88\x6f\x8c\xe4\xe6\xa6\x57\x36\x5d\x87\xb8\xb5\x43\x5a\xf5\x8e\xaa\x81\x49\xcb\xf2\xeb\x90\x08\x3c\xf6\xe6\x6e\xa3\x5c\x5c\x64\x8d\x02\x61\xe2\xe1\x1f\x6c\xff\xe2\xc4\x4d\x1d\xae\x7f\x7f\x78\x80\xb8\x6f\xef\x7f\xde\xd8\xe8\xf7\xdf\x27\xdf\xd0\xde\xfb\x87\x57\xe2\x30\xf1\xcd\xd2\x53\x34\xf3\xbe\xc1\x79\xf9\x29\xbb\xcd\x26\x6c\xb6\x79\x96\xdc\x5b\x53\x23\xbe\x9f\xe1\xb8\x8f\x80\xed\xcb\x81\x01\xa1\x9b\x3d\x82\x44\x8c\xef\xaf\x16\x57\x57\x30\x95\xe2\xcb\xf0\xbe\x2c\x3e\x58\x9f\xd0\x8c\x8d\xc4\x30\x9d\xc1\x84\xf2\x24\xd8\xe5\x08\x99\x6e\x89\xf7\x0d\x88\x85\x50\x0c\x73\xc8\xf6\xdc\xb3\x4e\x84\xb3\x0c\x85\x4b\x7c\x84\x59\xbf\x17\x12\x7f\xc1\x2c\xb0\x27\xd6\xbe\xb1\x2c\xbd\x0d\x70\xd3\x3c\xa1\x0d\xb8\xad\x8a\x55\xad\xc1\x6d\xd8\xd7\x34\xe2\x06\x84\xbb\x5d\xbb\x4d\x63\x9e\xe8\xf9\x8d\xe3\xef\x1e\x6b\x1e\xa5\xfa\xa3\x0d\xa4\x8f\xff\x05\x4d\x94\x0c\xd9\xf3\xdb\x28\x3f\x7c\xac\x91\x9c\xec\x8f\xb6\x92\xbf\xfe\x83\xcd\x5c\x8a\x03\xd4\x88\x96\x7b\xd3\x5e\x72\x4f\xde\xb6\x18\x15\xe5\x4c\xc0\xbc\xae\xe0\x80\x46\x6b\xde\x95\x3f\xda\xda\x4e\xe7\x86\x7b\x12\x66\x4b\xb8\x70\x4e\x18\x7b\x7c\xc2\x68\x10\xe6\xf8\x35\x59\x0a\xb5\xc8\x72\xfc\x86\x4c\x80\xba\x0d\x41\x57\x90\xe4\xf8\x0d\x59\xff\x74\x13\xe4\xb8\xff\xe3\x1b\xd1\x41\x8f\xe3\xfe\x4f\x64\x7d\xc5\xe4\x38\xee\xbf\x45\xff\x16\x3f\x3d\x4f\x5b\xc1\x12\xcd\x66\xc6\xb0\x05\xfa\xfd\x0b\x62\xd9\xee\x22\x37\x10\x41\x4c\xbd\xb8\x62\xc9\x53\xd8\x57\xba\xa2\xf7\x57\xe5\xf7\x8f\x93\xec\x3b\x82\x8c\xcb\xc7\x3f\x57\xe5\x62\xc6\xa0\xe3\x93\xc5\x14\x26\x0d\x1e\xf8\xe0\x75\x2c\x93\x8d\x39\xcd\x37\xf5\xcc\x48\x6a\xb7\x99\x7a\x3f\xbd\x81\x22\xbe\xaa\xb7\xcf\x19\x9a\xba\xc9\xd8\xb2\x98\xff\x9a\xa1\x7b\x69\x7c\x9b\xc0\x79\x77\x77\x92\x4e\x67\xea\xe5\x17\x1d\x05\xc3\x32\xcc\xe7\x77\xf4\x58\x21\x4c\x0c\x3d\xc0\x5a\x28\x6a\x7c\xfc\x96\xa3\xbe\x00\x3e\xfd\xe3\x00\xcf\x09\xf4\x54\x96\x53\x2a\x23\x9f\x4c\x8e\xcc\xe7\xd0\xde\xf2\x6b\xb6\x97\xd6\x37\x25\x99\x1d\x9b\xb0\x56\xa2\x5f\xf3\xd1\xfc\x06\xc1\xd5\x45\x99\x9c\x07\xbf\x66\x57\x5f\xf3\x79\x20\x82\x69\x0d\xff\x0e\xcb\x7f\xc0\xff\xa3\xe0\x62\x60\x4b\x1f\xf2\xc8\x6b\x64\x50\xb6\x43\x91\xb7\x3b\xaf\x08\xe3\xfc\x22\xc9\x11\xbb\x29\x5a\x2a\xdc\xb9\x7b\x9c\x53\xd7\x15\xda\xd5\xc5\xd6\xf3\xc1\x34\xbd\xa6\x5e\x33\x41\xda\x29\xb2\x13\x7a\xc2\x12\x78\x27\x6c\xb7\x9c\x94\x15\xb5\xe5\x8a\x3b\xf0\x9e\x7f\x55\x1b\x65\x30\x3b\xd3\xd2\xaf\xcd\xaf\x3e\x94\xf3\x39\xf4\xea\xbd\xfd\xd6\xc8\x81\x03\x1b\xf9\x70\x60\x33\x37\x34\x05\x57\x79\xe1\x73\x23\x27\x0c\x6a\xe4\x83\x41\xcd\x5c\xc8\x3b\xb9\xca\x86\x5e\x1a\xf9\x50\x58\x23\x23\x0a\x6b\xe6\x74\x56\xce\x54\x3e\xf0\xd8\xc8\x05\x42\x1a\x79\x9c\x21\x05\x54\x39\xe0\x4c\x8e\xef\xf1\xbf\x4e\x85\x2f\x7f\x65\x9d\xa3\xf6\x5c\xa7\x94\xf9\x3f\xb2\xf6\x54\xc7\x98\x8f\xe9\x34\x9f\xdc\x11\xae\xbf\xa8\x93\xfb\xbc\xfe\x52\xe4\xf3\x09\x90\xd1\xcf\x74\x6b\x11\xe7\x02\xa6\x6f\x85\x60\xc6\x23\x75\x67\xb9\xff\x7d\x86\x90\x17\x40\xd6\xe2\x74\xd9\xf0\xdc\x8b\xf4\xe3\xe9\xde\xc8\x5f\xee\x9e\x9e\xaa\x5c\x8d\x1a\x46\x07\x73\x5a\x26\x21\xeb\x2e\xc1\x26\x34\x81\xf6\x50\xeb\xc9\x7f\x60\x24\x28\x62\x84\x4a\x66\x30\x05\x6b\x8a\xa1\xfb\xb4\x20\xd2\xfe\x89\x6e\xee\x66\x37\x59\x81\x4e\xbe\xad\xef\xa4\x06\xc9\x34\x9b\x96\x94\x23\x12\xa8\xa3\x62\xc2\x0a\xa6\x5c\x9c\xc1\x85\xa8\x7d\x18\xcb\x29\xc1\x4f\xa0\x11\x5d\x30\xac\xeb\x8f\x93\x32\x85\x16\xe6\x36\x67\xc8\x3a\x15\x08\x06\xd9\x09\x3a\x80\x35\xea\xa9\xcf\xe9\xec\x1b\x50\x18\x67\xa7\x8e\xba\xf7\xac\x95\x75\x98\x56\x5f\x17\xb3\x8f\x25\xaf\x20\x17\x78\x96\x25\x04\x81\xb9\x4b\x20\xc4\xe1\x39\x62\xaa\xcc\xdb\xb8\xde\xfa\x32\x0f\x15\x8a\xf9\x5c\x8c\xca\xc1\xd9\x26\x9c\x94\x8b\x68\x33\x88\x03\x01\xcf\x25\xc2\xad\xc0\xdb\x20\xd0\xe7\xe4\x8c\xa5\xb8\x04\x02\x47\xfd\xec\xab\x0d\x6e\x0d\x7c\x54\x94\x2d\xd4\x95\xca\xbb\x81\x5e\xf2\x48\x09\xb9\x4b\x38\xce\x67\xe7\xf9\x05\x9d\xe7\x83\x31\xf5\x04\x74\x62\x4e\x72\x87\x21\x0c\x6b\x54\x40\x6c\x92\x9a\x03\x7e\x9d\x54\xbd\x15\x93\x15\x52\x63\x56\x75\xa4\xef\xf0\x09\x54\x19\xb2\x59\x68\x5d\x93\x35\xca\x33\x08\x96\xae\xaf\xf9\x89\x44\x43\xb2\x66\x6b\xfc\xd3\x9b\xc7\xf6\xec\xf6\x44\x8d\xfb\xaf\x49\x5d\xc8\x37\x53\x21\x8e\x72\xf4\xcc\xd3\xb8\xff\x33\x45\xb5\xa7\x29\x6c\xd9\x14\xd3\x00\xe7\xf8\xe9\x59\xe0\x1c\xac\xa9\x39\x94\x1c\x46\xcd\xbc\x91\x0c\x64\x94\x37\x0e\xb3\x15\x08\xf9\x2c\x4b\xd8\xd0\x0a\x0b\xa3\xd7\x42\x58\x91\x2b\xcf\x52\xf5\x1e\x94\x08\x79\x6b\x5c\x91\x64\xc5\xef\x8b\x6c\x91\x35\x66\x4d\xb3\x42\x8d\x77\xa3\xc7\x6d\xea\xe7\xbe\xda\x29\xd4\x57\x0d\x85\x5e\x95\x54\x5d\xff\x2c\x05\xab\xaa\xee\x4c\x26\x1d\x7e\x0b\x4c\x56\x22\x6b\x94\x37\x60\xbd\x14\xa0\x05\x4a\x99\x3b\x49\x94\xe6\x7e\xd4\xac\x48\x67\xff\x5a\x6a\x02\xad\xdb\x32\x54\xff\x9f\x6b\x25\x6c\xc2\x50\x1f\xe8\xc2\xb6\x44\xa6\x1f\x11\xf4\x33\xab\xb3\xb6\x98\xfc\x29\x03\x0c\x4c\xb8\xf6\x0c\xd3\xfc\x9e\x72\x0d\x23\x74\xff\x92\xa3\x6d\x1d\xce\x00\x44\xbb\x84\x11\x8d\x44\x4b\x81\xd4\x03\x25\xe3\x4e\x9a\xf8\x67\xe2\x3c\x5b\xba\xb2\xaf\x1f\x03\x36\xf1\x19\xa6\x07\xa7\xfb\x9f\xf6\x77\xcf\xd8\xb8\xba\x80\xf3\x35\x2e\x9b\x87\x87\xe0\xe0\xf3\xf1\x97\x46\x28\x8a\xe2\xf3\x49\xc6\x81\x38\x09\xbd\x00\x51\xdf\x2c\x79\xcd\x51\x8f\x6d\x77\xc5\x01\x62\x4e\x5d\xad\x16\xcd\x64\x91\xf8\xde\xbb\xa2\x17\xe9\x8d\xa5\x0e\x4b\x07\xbc\x9f\x04\xef\x97\x3d\x39\xf3\xf9\xac\x81\xd3\xf2\xb2\x27\xe1\xbb\x28\xe8\xff\xc1\xc8\xb0\x8d\xf9\x7f\x96\xcc\xe1\x08\x93\x89\xb3\xa6\x79\xa5\xb2\x2f\xce\x1d\xa4\x7f\xf8\x00\xe8\xe5\x19\x49\x8c\xbd\x89\xc5\x19\xcf\x86\x03\x89\xc0\x6e\x0b\x9c\x1d\x00\x4b\x94\x0a\x1e\xd2\x51\x8c\xbe\xdd\x2e\x18\xcd\x76\xab\x25\x54\x66\xb3\x7b\x4a\x4a\xf7\x31\xdb\x21\x82\x1e\xa2\xd3\x65\x54\x00\xd3\x71\x78\xb6\x43\xb0\xcb\xa8\x25\x50\x55\x4d\x3c\x86\x01\x22\x25\x6e\x38\xa7\xc9\xe9\x04\x83\x62\x6d\x16\x7b\x19\x3b\xff\x80\x55\xe3\xde\x40\x19\x02\x23\xad\x5e\xba\x2c\x5c\xce\x54\x02\xb1\x13\xb5\xbb\x74\x26\x93\xa9\xde\x1a\x47\xb6\xd0\x94\xbb\x76\x94\x4d\xb2\x79\xb6\x76\x26\x6b\xda\xea\xe9\x76\x1e\x6e\x8f\x9b\xa3\x68\xa3\xff\xc7\x52\x3b\x58\x56\x90\xa6\xab\xca\x8c\xdc\x18\xeb\xdb\x80\xba\x1a\x2a\x46\x82\xd2\x0e\xf0\x2e\x02\x25\xe8\xc7\xd0\x89\x39\xdf\xc2\xe9\x6c\x6f\xba\x86\x95\x4e\x85\x9e\x51\x1d\x75\x8d\x2a\xea\xff\x4f\xfc\xa3\x3a\xb3\x47\xf5\xb6\x59\xe2\xba\x4c\x7b\x0a\x5d\x47\x49\x78\x46\x6d\x6c\xe8\x18\x3a\xbb\xbb\xef\x78\x7c\x7f\x78\x58\x3f\x7b\x78\x90\x5d\x0d\x25\x1e\x2b\x75\x55\x68\xa9\x1a\x80\x03\xab\xe4\xa9\x45\x20\xbc\x94\x20\x0c\x60\x99\x0e\xbf\xc2\xd9\xd3\x90\x03\xa0\x1a\x55\x3a\xca\x4b\x13\x62\xe5\x78\xdd\xb9\x28\xd0\x11\xb0\xe9\x3d\xc6\x9c\xf6\xcb\x66\x2f\x6d\xd9\xec\x64\x71\x9d\x17\xbf\x2c\xae\x0c\x58\xa5\x47\x66\xbb\xbf\x92\x2d\xfe\xae\x60\x26\xd3\xe1\x5c\x52\x1c\x83\x51\xa9\x0f\xfd\x4a\xfe\xba\xab\x40\x2d\x29\xe0\x94\x51\x04\x51\x63\x5c\xc1\x55\xe6\xb5\x16\xef\xc9\x59\x65\x80\x2b\x95\xd4\xf6\x30\xb9\x6b\x48\x2e\x8f\x80\x39\x65\xd8\xf5\xc7\xa5\x46\xa7\x24\x0e\xe2\xd4\x4d\x51\x91\x15\xb7\x5a\x3e\xa4\x67\x9b\xb0\x88\x92\x30\x63\x21\xcc\x54\x15\x66\x7e\x0b\x7b\x3a\x09\x33\xd7\x84\x6f\x42\xa2\xb4\x68\xc5\x5a\x15\x5f\x93\xf5\xfe\x60\xdf\x91\x01\x7f\x4d\x76\x71\x4e\xd1\x52\xc7\x0b\xb2\xf5\xb0\x53\x18\x1d\x79\x40\xc8\x30\xcd\xfb\x9f\xe5\xd5\xd6\xe7\x76\xf6\x9f\x31\xfb\x1c\x1b\xf2\x87\x73\x7f\x2b\x73\xdf\x49\xee\xbd\xf6\x6b\x6b\x7b\x48\x64\x8d\xa9\x57\x44\x3c\xbe\x73\xc6\x38\x46\xd5\xe0\xb9\xd8\x43\xfc\x5d\x1b\x3e\x14\x2f\xfb\x3f\x39\x12\xb5\xa3\xd5\x12\x35\xa9\xcf\x52\x8a\x94\xb0\xf3\xf1\x42\xe7\xeb\x76\x99\x2c\xe2\x34\x19\xc6\x27\xf8\xfa\x19\x5e\x6f\xe2\xb0\x4c\x6e\x81\x97\x1c\x45\xf1\x94\x95\x69\xca\xe4\x1a\x78\x4e\xa5\xa8\x5b\x2a\x67\x0e\xc4\xdc\x4b\xbd\x27\xef\x06\x5e\x43\x91\xea\xae\xe5\x91\x7d\x9c\xae\xfa\x96\x29\xa2\x17\x4a\x05\x65\xfb\x3c\xf0\xe9\x71\xf1\x9e\x5e\xd9\xf1\x9b\xad\x3f\x2a\xf4\x73\xd6\x74\xdc\x67\xe4\xd1\xc6\x92\x86\xe0\xb7\xc2\xb7\xa2\xe1\x68\xb0\x25\xfc\x0b\x1a\xa2\x5e\xb5\xc4\x7e\xaf\x1f\x43\x04\xe2\xb3\xe2\x16\x29\x65\x48\x84\x2b\xa8\xde\x49\x59\xce\x59\x10\xd6\x9e\x4b\xd5\xe6\x66\x4b\xef\x02\x4b\x7a\x0e\x8a\x8f\xdc\x7c\x7a\x79\x51\xc3\xd6\xc7\x57\x19\x28\xcb\x62\x48\x49\xd4\xde\x40\xdb\x44\x3e\x8f\x46\xf6\x09\x65\x8f\xce\x58\xe6\x70\x42\xb5\x3d\x5c\x4c\xe6\x39\x21\x37\x71\xb7\x36\x7c\x18\xc3\x8c\xc6\xce\x22\x6c\xeb\xc2\xf2\x63\xe8\xba\x54\xbd\xd7\xc7\xb7\xc9\xdd\x09\xeb\x48\x61\x3d\xd0\xa3\x00\x9f\xcd\x51\x23\xf9\x91\x24\x82\x8d\xe6\xac\xd2\xe2\x54\x48\x06\x50\x8e\x78\xe3\x50\x64\x2c\x73\x16\x4c\x7f\x86\xfc\x33\x49\xb6\x06\x93\x77\xfa\xb0\x30\x81\x83\x02\x1a\x15\x25\xa4\xdd\x57\xd0\x0e\x06\xbb\x54\xd9\x3b\x3c\xfa\xeb\xfe\xe5\xfe\x7f\x1d\x9c\x9e\x1d\x7c\xfe\x33\xf4\x97\x89\x39\xd9\xa7\x38\xf4\x64\x14\xc9\x9b\xf2\x82\x6e\xab\x68\x5c\xc5\x38\x41\x04\x08\x34\xd3\xc3\x26\xd8\xfd\x3e\xbb\x10\x37\x3a\xf2\x60\x6f\x50\x87\x63\xec\x9f\x05\x29\x86\x2f\xce\x6f\x2e\x12\xfc\x47\x87\x31\x7c\x80\xf4\xc9\x18\xaa\x3d\xa4\x10\x09\x25\x34\xe6\x41\x1b\x25\x8d\x3e\x43\x84\x6e\xee\x2a\xbc\x35\xa7\x2b\x7d\xd5\x03\xb7\xd0\xe2\xdb\x77\x0a\xbe\x67\x70\x0b\x2d\x1e\x9e\xdf\x5e\xd8\x95\x54\x16\xa5\x50\xd5\x10\xe3\x8c\xaa\xdd\x14\x3e\x9e\x9a\xee\x9a\xc2\xc7\xf2\x52\x1a\xbb\x6c\xaa\xba\x4c\x5e\x50\x97\xbd\x83\xcf\xa7\xfb\x27\x67\x97\x87\x3b\x27\x7f\xf9\x72\x1c\x57\xa1\xdd\x17\x62\x74\x5e\xf4\xa6\x54\x49\xea\x2a\xfa\xb8\xa4\x47\x38\x28\xc0\x1a\xf9\x3a\x90\xb9\x38\x9d\xdf\xcc\x65\x71\x6e\xfa\xf0\xe2\xdc\xea\xfa\xee\xfc\xce\xf6\xff\xeb\xec\x72\xf7\xe8\xf3\xd9\xfe\xe7\xb3\x38\x75\xb3\x83\x6f\xcc\xac\x6a\x7c\x67\x0d\x75\xec\x8a\x38\xd8\xe6\x51\xad\x9a\xf8\xf5\x4f\x62\xf5\x9a\x89\xfb\x8c\xc5\xdc\x04\x0c\x6e\x2d\xa2\xf8\xd5\x16\xea\x56\xbd\x7e\x0e\xd2\x8e\xb9\x55\x08\xe7\x1b\x59\x44\x1e\xcc\xac\xa5\xed\xc2\x70\xde\x1f\x7e\x39\x3d\xbb\xfc\x72\xba\x7f\xb9\x73\x76\x76\x72\xf0\xe1\xcb\xd9\x7e\xdc\x17\x3a\xf0\xf8\xe4\xe8\x18\x46\xf0\x7f\xc7\xaf\xc4\x2f\x3b\xa7\x97\xa7\x07\xe8\xaf\xeb\xe3\x47\x38\x2e\x9e\xc6\x3f\x52\xd0\x87\xa3\xa3\x4f\xfb\x3b\x9f\x2f\xff\xba\xf3\xe9\xcb\x7e\xfc\x33\x85\x7d\xfe\x72\xb8\x7f\x72\xb0\x2b\xc3\xfa\xaf\x29\xf0\xf8\xe8\xf4\xe0\xec\x00\xfb\xcf\x89\xfd\x91\x3f\x81\x8e\x3d\xf9\x74\xb4\xb3\xb7\xbf\xd7\xc8\xf1\xf5\x8f\x82\x3d\x1f\xc1\x2e\xae\x8e\x1e\xbb\x64\x9e\xef\x73\x1d\xd9\x93\x49\xf2\x8c\x5d\xa8\xa0\xf8\x0c\x3e\xdc\x99\x43\x3f\x5d\x2d\xe6\xc4\xba\x72\x4c\xca\x31\xc7\xd6\xa9\x80\x23\x16\x1c\x71\xb8\x98\x13\xff\x75\x98\xcd\x6f\xca\x11\x45\x0d\x80\x90\xd6\xbb\x8b\x7a\x5e\x4e\x75\x86\x68\x50\x72\xd9\x0a\xfd\x28\x6b\xa6\xe4\x26\xed\xef\xcc\x9a\x1a\xb2\x3c\xef\x3e\x0f\xd7\x11\xea\xf8\x14\xb6\xc3\x51\x5a\x8d\xb0\x42\x1e\x93\x2b\xd1\x4c\x83\x96\x57\xeb\x5b\x52\xc8\x39\x84\x19\xff\xa9\xfc\xa6\x6e\x8e\x68\x53\xe7\xbd\xbc\xae\x73\xe0\x1f\x9d\x0f\x27\x17\xc9\x50\x78\x8c\xb6\x34\x19\x83\xac\x07\xdd\x9f\xcf\xf0\x73\x8a\x76\x7a\x17\xeb\x33\x5b\x92\x38\xd0\x1f\x39\x91\x79\x5a\x1d\x8f\xc1\xa9\xc7\x7a\x2c\x85\x88\x58\x16\xe2\x8e\x07\x7e\xb1\xf0\x7c\x81\x3e\x0d\x63\xad\x3a\x32\x4e\x32\x6e\x03\x7a\x04\x06\x46\x50\xd7\x05\x3f\xaf\xc2\xb1\x00\xda\xd2\x9a\xfe\xd8\xc5\x32\xbd\xca\xd9\x93\x5c\x2d\x0c\x4c\x0d\xd5\x38\xcd\x47\xd9\xfe\x78\x0c\xd3\xb4\x36\x89\x9b\x2b\x46\xa6\xfd\xc0\xd6\x0b\x24\xb8\x74\x13\x3b\x33\x5f\xa6\xfe\x8c\xd0\x14\xf9\xd0\x93\xda\x59\x47\x32\xb5\xba\xd2\xeb\xfe\xca\xbf\x0c\xe5\xe7\x47\xb7\x59\x35\x29\xd3\x51\x36\xea\xae\x64\xd7\x4a\x45\x54\xbb\x75\x6f\x57\xc3\xd1\xd3\xd7\xa5\xf8\x81\x2f\x9c\x92\xb7\xfa\x94\xb2\x5f\xf7\x75\xe0\xa6\x0c\x6e\xb4\x59\x05\x77\xb6\xe9\x5d\xd2\x27\xc3\x2e\x74\xdf\x84\xb7\x37\x07\x7b\x66\x12\x5c\x7e\xde\x39\xdc\x8f\x49\x13\xf0\x05\xd9\xa6\xe7\xa3\x40\xb8\x0b\x2f\xbe\x27\x08\x37\xdf\xda\x90\x51\xce\xd4\x57\xc9\xad\x69\x2f\x83\xdc\x99\x8d\x81\xcd\x3e\xb4\xc2\xd4\xf7\x18\xe4\xf6\x91\x0c\xb1\x1b\x29\x83\xec\x8e\x91\x41\xbe\x79\x22\xa3\xfc\xfd\x85\x91\x2b\xe8\x5c\x0c\x3c\x49\x2b\xb6\x03\x63\x63\x6b\x90\xbd\x5b\x4d\x34\x25\x7b\x91\x29\xd4\x96\x22\x59\x99\xfe\x3c\xa3\xbb\x89\x82\x3c\xf5\x29\x8f\x98\x5a\x0d\x14\xbb\x58\x82\xa6\xaa\xdb\x16\xdd\x89\x9e\xfb\x16\x51\x25\x29\x7a\xf0\x53\x5c\xf8\xc3\x43\x88\xef\x49\x85\x4e\xbe\x04\xf9\x02\xc3\xb0\xc2\x5c\x48\x35\x1c\x9b\x44\xa2\x42\x5b\x88\x02\xfe\xf1\xe3\x52\x6e\x60\x78\xff\x5b\x36\xaf\xfc\xbc\x52\xdc\xc7\xf0\xb9\x3a\x74\x08\xa4\x6f\xd5\x87\x87\xbc\xb5\x4a\xe6\x17\x1b\x1b\xeb\x2a\xc6\x59\x28\x18\xc3\x76\xaa\x59\x24\xe3\xbd\x44\x04\xd3\xf5\xdf\xab\x2c\x3a\x16\x15\x26\xca\xc8\x7d\xa6\x73\x98\x30\xdb\xac\x39\x51\xfc\xbe\x28\xe7\x66\x86\xab\x91\x91\x20\xb9\x74\xa8\x68\xde\x20\x36\x6f\xf0\x0e\xf6\x7c\x5e\x1f\xf3\x5e\x6b\x1d\x93\xfd\x57\x49\x7a\xfd\x8d\x2c\x3a\x26\x02\xaa\x26\x3e\xb2\x15\xa3\xa9\x4a\x33\x0d\x34\x9f\x2d\xe3\x58\xd5\xd3\x31\x87\x2a\x80\x45\x6f\xed\x86\x66\x9a\xf9\x46\xec\x89\x5d\xbd\xb5\x5d\xc4\x85\x6c\xa2\xb1\x8b\xc8\xdb\x2c\x07\x1a\xec\xc8\x29\xb2\x1d\x04\xf1\x5c\x7f\x13\xb7\xae\x23\xbd\xfd\x22\xed\xfe\x1e\xeb\x99\xcc\xd7\x33\xb0\x16\x58\x5c\xc1\xdd\xd0\xd8\xcc\x79\xfd\x96\x51\x49\x5e\xaf\xf8\x2e\x91\x85\x1a\x28\x20\xa5\x0b\x14\x16\x15\x37\xeb\x47\x1d\xad\xd3\xe7\xed\xcd\x07\xca\x9d\xa3\xa8\xc5\x74\x82\x67\x18\xb2\x0b\x11\x04\x9b\x85\x63\x0b\x9e\xb7\x78\x14\xac\x64\x73\x5b\xca\xd0\x52\x3c\xd8\x24\x33\x22\x14\xec\x14\xe8\xc1\x11\x5f\x50\xe4\xc1\xd5\xf2\x8c\x83\xed\x99\x6a\x7b\x2e\x8f\x5b\x76\x74\xdc\xa8\x73\xc6\xf5\x23\x39\x9e\xaf\x1b\x9e\x3f\x7d\x57\x0e\x52\xb1\x62\x90\x8a\x08\x0b\x61\x49\xed\xe3\x3d\xdf\x6c\x9a\xb7\xf3\xad\x7e\xaf\xbc\xfd\x2e\xe4\xac\xe9\xa0\xe2\xa1\x91\x4a\x93\x02\x7b\xe7\x20\x55\x17\x78\x62\xa7\x21\x82\xc7\xf2\xb1\x21\xf2\x8d\x0c\x3a\xa7\x6a\xb9\x9c\xb0\xe9\x5b\xfc\x9a\x04\x53\xab\xa9\x1b\x9c\xea\xfa\x9e\x8b\xe7\xd7\xcf\x80\x17\xb4\xfd\x54\x5b\xda\x61\xc2\x42\x67\x21\x93\x33\x8b\x0c\x77\x6a\x86\x58\xa0\x36\x24\x9a\x40\x94\x6e\x26\x91\x46\xb8\x93\x4d\x67\xf3\x3b\xb5\xe3\x1a\xd9\x0e\x4e\x13\x4a\x89\xde\xd7\x35\x3e\xb2\x73\xc6\x1c\x22\xd6\xc0\xbb\xf3\xff\x5e\xfb\xdb\xcb\xf7\x17\x9b\xd1\x4b\x31\x49\x98\xaf\x62\x89\xc5\x0b\xaa\x6f\x80\xe8\xc9\x1d\x22\x0c\x87\xca\x2f\x42\x4b\x3d\xc4\x1c\xa2\xd0\x09\x0c\x70\x28\x33\x60\x2e\x66\x46\x3e\x31\x03\x06\x62\x01\xa3\x3d\x43\xc7\xf6\x88\xc7\x22\x9f\xf0\xa6\x71\x3b\x8b\x83\xff\x0c\x44\xa1\xf6\x6a\x12\xab\xe0\x03\x1e\x6c\x30\xa1\x3c\x41\x9c\xa3\x98\x66\x8b\x0a\xa2\xcd\xbf\x20\x01\x51\x7b\x3d\xf1\xd2\x19\x89\x5b\xca\x8d\xd2\x8f\x30\xfd\x2d\xa6\xbf\x6d\xa6\x1f\xc9\xf4\xd3\xe4\xf6\x7c\x04\x45\xc1\xbf\x64\xaa\x6d\x06\x87\x22\xf8\x8f\xfe\x5a\xb0\x39\xd9\xfc\x13\x42\xfe\x8d\x36\xff\x14\xac\xfd\x29\x5a\xaa\xc6\x5e\x27\x25\xe4\x48\xc6\xa6\x68\x36\x9d\xa2\xd6\xf8\xd6\xe0\xee\xdd\xb5\x6a\xf7\xe6\xe6\x1d\x67\x7f\x99\x5c\x9f\xdf\x5d\x0c\x2e\xb1\x78\xeb\xc8\xea\xbe\x87\x13\xa4\x47\xa3\x64\xf3\xd2\x59\x9d\x28\xc5\xbd\x6c\x2d\x01\x08\x5c\x84\xeb\x63\x4f\x7b\xc4\x18\x1b\x71\x29\x08\x23\x5c\x83\x7b\x2c\x42\xbc\xce\x1f\xeb\xeb\xfc\x45\x38\x36\xb7\xfc\x1a\xd4\x43\x8c\x81\xb4\x3d\x26\x17\x74\x89\x9c\x3b\x11\x04\x9a\x87\xc0\xbf\xe0\x66\x3e\x9d\x04\x84\x52\x34\x4f\xaf\x89\xf2\x39\x27\xe2\x48\x6e\xc6\xb0\xed\x41\xbf\x9d\x6f\x5d\x0c\xe6\xae\xe4\x8b\x0a\x66\xd1\x57\x41\x52\xf9\x16\x4a\xf2\x6a\xad\x15\xef\x2a\x8a\xfb\xaf\x49\xdc\xe3\x2e\x22\x08\x25\x91\xb7\xbb\x86\x80\x07\xec\xb8\xdb\x7f\x1a\xf6\xa2\x73\xd7\x94\x27\xe7\x55\x78\x7f\x92\xd5\xb3\x12\xd7\x93\x25\x5c\x57\x97\x47\x10\x7d\x9a\x4f\x67\x93\xcc\x1f\x77\x96\xce\xfc\x11\xfb\xe8\xe1\x89\x3c\x39\xf9\xe3\xf9\x16\xa8\xa3\x40\xba\x2a\xf2\xc7\x59\xea\xf6\xfe\x04\x3b\x45\x3a\xb9\x43\xbf\xe9\xfe\x68\x46\xb3\x62\x30\x2b\xba\xcb\x6a\x27\xbb\x68\x1b\x33\xba\xb2\xfc\xc7\x54\x78\xad\x8e\x6e\x5d\x50\xe6\x9d\x17\x91\x65\xe3\x52\x91\x14\xab\xd5\xcd\x62\x6a\x8b\xd9\x51\x6f\xd7\x90\x58\x35\x96\x8b\xa4\x6a\xdc\x1b\x0e\x93\x14\x57\xec\xc7\xbc\xaa\xe7\xf4\x25\x7a\x22\x9c\x24\xf7\x53\xca\x19\x07\x28\x86\x4d\xc2\xbd\x4a\x8c\x6b\xbc\x24\x3c\x34\x29\x64\xd7\xb9\x17\x84\x0b\xad\xf9\x7d\xb4\x98\x0b\xeb\x0d\x78\x51\x38\xcf\x50\x01\x34\xf8\x2b\x0b\xe0\x14\x7f\xa0\x00\x24\xe4\xe7\x6c\x00\x05\xff\x2e\xc4\xd8\xb9\x18\x9b\x3c\xaa\x6a\x2e\xed\xb0\xdc\x6c\x09\xb8\xb3\xca\xf0\xca\x6a\x74\x96\x56\xd7\xe8\xc9\xa8\x22\x71\xb1\x3c\xba\x45\x8e\xe9\x11\xe6\xb1\xee\xe4\xb1\x98\xf3\xad\xba\x9b\x6d\xcb\x5e\xa9\x66\x03\x6b\x36\x79\x41\xe1\x6b\x54\x27\x99\x61\x71\xc6\x49\xd6\x2b\xbf\x15\x59\xb5\x27\xcf\x8f\x83\x3a\x19\x6f\x8f\x95\xef\xb2\xbf\xe6\xd9\xb7\x87\x87\xb1\x24\x4a\x0c\xb0\x26\xf1\xb4\xd9\x68\x49\x8c\x06\xed\xe6\x2d\xe6\xdb\x40\x67\x33\x31\x4a\x86\xbe\x46\xce\x4b\xd5\xc4\x87\x87\x3a\x8a\x21\x69\x0d\x49\x33\x74\xa6\x95\x24\xa3\x56\x0b\x6e\x93\x9b\x6d\x9a\x59\x07\x7b\xe1\x4d\x14\x07\x81\x98\x26\x23\x1d\x32\xa2\x10\xd8\x83\xac\x4b\xc2\x49\xcf\x4c\x09\x71\x8b\x5c\xd8\x35\xdf\x90\x04\x14\x3e\xc1\x70\xf8\x06\x68\x32\x56\x29\xb9\x81\x47\xa7\x92\xc9\x48\x7a\x9a\xf6\x64\x4a\xd3\x54\x4c\x2d\x4b\xaf\x3b\x3b\xef\x0c\xa3\x03\x71\xa7\xf2\x1e\x89\xbb\x46\xde\x37\xa8\x72\xa5\xaf\x2b\x0d\xe1\xb2\x2e\x2c\xaf\xc5\x1d\x54\x7b\x1a\x89\x19\x6c\x09\xc9\x35\xfc\xf4\x2f\x92\x3b\x31\x73\xc8\xff\xf8\x8f\x98\x25\x58\x2b\x3a\xee\xb3\x4b\x46\x1f\x05\x88\xfb\x3f\xfd\xd0\xbe\x54\x7c\x86\x2e\x30\x7c\x78\x98\x23\xea\x1d\xd1\x20\x20\x84\x4a\x61\x80\x6f\xbb\x94\x8a\x80\x5c\x8c\x08\x4e\x77\xaf\x2c\x68\x59\xa1\x4d\xa9\x01\x98\x57\xa4\x9e\xe6\xad\x6d\x69\xd4\x08\x36\x36\x3a\x8d\x08\xcb\xb0\x85\x63\x48\x69\xee\x30\x2b\x16\x56\xd8\xec\xce\xbc\x2c\x4c\x36\x7b\xe5\x02\x5a\xe1\x56\x65\xaf\x4a\xaf\x9d\x17\x5d\xa1\xff\xa5\x03\x14\x65\xd3\x49\xbe\xe7\x73\x27\xc0\xd0\x26\x15\x82\x8b\xd9\x09\x70\x1b\xb4\x07\x63\xab\x5f\x08\x5f\x50\xbf\x91\xa2\x84\x7e\x33\xb6\x64\xc2\xb2\x78\xb6\xde\xd9\x26\xd3\x0a\xf8\x62\x32\xfe\x04\x07\x7d\xfd\x62\x6c\x9e\x9d\x90\xc3\xd2\xaa\xb9\x5a\xff\x8d\x00\xbb\x2d\x14\x62\x95\xc1\x26\xa3\xea\xed\x84\xf4\x1d\xd5\x1b\xfb\x20\x32\xaf\xae\x52\x87\x09\x5f\x5c\x4d\xad\x0e\x35\x06\xb5\x3a\xa4\x5c\x0c\x6f\xd8\xff\xa9\x1b\x66\x4f\x1e\x0a\x70\x5a\x43\x21\x6e\xbf\xff\x7a\x93\xc9\x3c\x96\xb8\x4d\xde\x3b\x5b\x60\x5c\x0a\xb5\xe6\xa0\x92\xa4\x86\x50\xc7\xf9\xb2\x7d\x44\x33\xcb\x03\xd6\x16\x02\xb2\xbc\xf6\x28\xf9\x5a\xcb\xa9\x79\xdc\xc9\x93\x7b\xc6\xca\xed\x72\x51\x3d\x6f\x7b\x4c\x08\xdb\x61\x84\xfc\xbc\xde\x8f\xd0\x31\x0f\xf2\xd5\x8e\x9e\xa8\xd7\xb7\x82\xfc\x00\xce\x9d\xf1\xdc\x56\xb1\xa3\xdc\x5d\x8d\xbb\x60\x93\xa0\xa3\xbd\x59\x37\x14\xeb\x38\x29\x66\x2a\x75\xae\x14\x85\xf8\x57\x34\x6f\xeb\xb9\xcd\xdb\xa2\x9a\xa8\x6f\x2a\x52\xc2\x45\xa6\x02\xf6\x48\x69\x52\x6c\xe5\xe3\xc3\xa2\x68\xf3\xd5\x30\xc2\x6f\x1e\xd3\x85\x6d\xb2\x71\xcc\x24\x4a\xdd\xab\xbb\x26\x2f\x47\x91\xca\x35\x70\xa9\xdc\x3d\xab\x5d\xe5\xa0\x98\x97\x86\x8d\x93\x56\x44\x3b\x3a\x7a\xd4\xa9\x0d\xb1\x34\x9a\x08\xf6\x31\xd7\x40\xf5\x65\x49\x4e\xf8\x78\xe8\x16\x5c\x6e\x58\x70\xd6\x25\x0f\x08\x5c\xa7\xc3\x72\xb4\x98\xa0\x74\x81\x47\x77\x1e\x0d\x8a\x8d\x8d\xa2\xf9\x0d\x5a\x26\x24\xad\x50\xd4\x46\x6e\x04\x65\xf5\x41\x71\x84\x66\x33\x74\xcc\x42\x79\x42\x7d\x8c\xa8\x1a\x38\x60\xf3\x30\x42\x9c\x0c\x5b\x5b\x54\xd9\xac\x93\x02\xd3\x8c\x9b\x02\xec\x9a\x91\x78\xcb\x47\x46\x1f\xc9\x7b\x3a\xa2\x67\x85\x4b\x01\xf9\x81\x84\x0c\x63\xa7\x62\xce\xb1\x7f\x86\x0e\x24\xc8\x07\xba\x3f\x89\x9e\xa8\x33\x25\x6d\xb7\x46\x8d\x9a\x13\x57\x3d\x7f\x44\x3b\x7d\xfd\x81\xaf\x67\x3c\x5f\xc8\xa8\xa5\x20\x7e\x14\x1f\x55\xbf\xf1\x9d\x74\x0d\x1f\x75\x45\x89\x26\xab\xcc\x23\x87\x9f\x74\xc4\x08\x20\xa9\x1e\xcf\x2e\x3c\x97\xeb\x70\xbd\x78\x78\xf0\x40\xa3\x14\x0a\xdd\x78\x41\x62\x8d\x10\x7f\xf0\xf2\x62\x50\xe1\x3d\x46\x41\xfd\xe8\xcd\x55\x49\xff\xf0\x03\xcb\xa3\x6f\x81\x56\x6f\x52\xf2\xf8\xf8\x77\xf0\x81\x54\xeb\xb5\xbf\xdb\x99\x4c\xd4\xa7\xb5\xff\x5a\x08\x65\x25\x8b\x48\x7e\x8a\x39\xd1\xd7\x8f\xa9\xc0\x69\xd4\x2f\x81\xf6\x2b\x33\x1e\x23\x1f\xaa\xd7\x42\xdd\x25\x49\x54\x2f\x58\x60\x13\x75\xd1\x3d\xe9\x39\xc5\xe8\xdc\x07\x08\x73\x81\xb6\x34\xa9\x98\x45\x46\xa4\x01\x5b\x8a\xa3\x7f\xee\xa2\xa0\x93\x01\x52\x19\x0e\x05\xaa\x0e\x2b\xa5\x24\xa3\x95\xde\x36\x8f\x18\x0e\x24\x05\x40\x65\xb9\x09\x1a\x4a\xad\x0f\xe1\xcb\xcb\xcb\xd9\x02\xd8\x57\x3b\x3d\x92\x0b\x8c\xb0\xc6\xef\x43\x5a\x7c\xf5\xac\x82\x45\x27\xe3\xda\x20\x72\xf1\x9b\xbe\xf0\x91\xb8\xf8\xcd\x2b\xd1\x26\x70\xc0\xa5\x92\x92\x8a\x87\xbe\xc5\x7d\x16\x80\xb4\xc4\x16\x6f\x9e\xe1\x2b\x8f\xfd\x3d\x6b\x55\xa5\x39\xcf\x09\xe5\x76\x1a\x26\x84\x28\x2c\x84\x5c\x06\xb8\x4a\xc3\xe2\xfd\x0b\xd8\x51\xd7\x87\x6a\xf8\xd1\xbc\xe3\x3e\x0d\x33\x77\x54\x23\x61\x27\x48\x14\x7e\x6c\xd6\x33\x27\x4b\x2d\x4d\x2c\xe9\x96\x2f\x4a\xc3\x3c\xac\x10\x36\x2e\x13\x25\x8e\xbf\x63\xec\xc0\x2d\x49\x61\xb0\x3a\x17\xbc\xc7\x66\x4c\x74\xa7\x26\xc8\x36\x8d\x6a\xdb\xa1\x08\x4c\xba\x9e\x16\x46\x17\x57\x94\xd0\x18\x3b\x6c\xc1\x6a\x02\x3c\x1b\x94\x0a\xc9\xb4\x71\x41\xba\x36\x6f\x11\x9f\xed\xb0\x0c\xdb\xa1\xf4\x35\xee\xd5\x08\xdc\x6d\xdb\x63\x58\x1d\xd1\x41\xc6\xf0\x5e\x4c\xac\x8a\x85\x93\x6b\x3b\x7a\xcf\x12\x18\x50\x1a\x6b\xa4\xd0\x96\xc7\x16\x28\xb0\xff\xbe\xf6\x06\x2b\xad\x75\xe4\x3e\x7b\x2f\xc7\x1f\x2f\xab\x3b\xe9\xf7\xfd\xb2\x93\x4e\x7b\xa2\xec\x4a\x62\x7c\xc7\xde\x63\x53\x08\xe8\xa9\x1a\x6b\xc6\xc8\x6b\x06\x84\x8c\xb0\x68\x15\x02\x99\xa8\xd0\x43\x5c\xe7\xce\xd4\xd6\x7c\x5a\xef\x3f\xc7\x6a\x31\x67\xab\xc5\x96\x06\x4d\x81\x10\xbc\x38\x11\x93\x24\xc7\x8b\xef\x70\x1d\xdf\x22\x41\x61\xb9\x20\x7f\x27\x4b\xf2\xaf\xc6\xfe\xeb\x7c\x1c\x88\x57\x2d\x6b\xe4\xf4\x32\x4b\x48\x9a\x7d\xa9\xe4\x10\xdd\x33\xa5\xfd\x8d\xd4\x5d\x75\xdb\x9e\x75\xad\x1e\x36\x9a\xec\x88\xec\xb6\xf0\x5c\x55\xa1\x8e\xcc\xa0\xbf\x2e\x78\xad\x2a\x3d\x02\x07\xc9\x47\x5c\x92\x41\x98\x3d\xb2\x8e\x57\x13\xd7\xa2\x4d\xd2\xc1\xd6\x68\xe1\x1d\xb4\xde\x30\xe7\x17\x03\x4d\xe0\xb4\x3d\x9b\x74\xd5\xd9\x4d\x74\x1a\x1d\x17\xb5\x2e\x0a\x0b\x53\x06\x79\xce\x79\xa4\x47\x06\x0d\xca\xe4\x21\x4b\x3a\x3f\xa4\x4b\x1e\x6f\x66\x9e\x2d\xe4\x79\x8e\x4b\x2d\xf3\x92\x69\xcf\x9c\x7f\x81\x73\x55\x21\xea\x24\xda\x0c\xe2\x03\xab\xdf\x17\xab\x9b\x1d\x9e\x5a\x9b\x5f\x63\x58\xc3\x52\xcd\xfb\x2d\x5b\xe3\xb8\xdf\xd2\x99\xb7\x65\xaf\xa6\x0c\x80\x2f\xd5\xf2\xd1\x3c\x14\x59\x38\xea\xe0\x83\x3d\xda\x18\x5c\x2c\x47\x98\xbf\x06\xca\x71\x6b\x90\xbf\x2b\xb4\x93\xbf\x75\xe2\xea\xcd\xc1\xf9\x14\xaa\x31\xcb\x46\xa8\x30\x08\x6c\x52\x86\xb7\xf0\x08\x92\x59\x91\x01\x31\x5b\xf6\x6e\x6c\x50\x30\xba\x33\x72\x81\xe1\x58\xc1\x5c\xfa\x57\x91\x12\xb7\xdb\x1e\xb1\xf5\x78\x46\x21\x04\x41\xcd\x91\x66\x7c\xc1\xaf\xb7\x1e\xf7\x33\xa2\xd5\x55\xc3\x8a\x8e\x0c\x43\xf9\x24\xd2\xee\x06\x69\x8c\xe9\xf4\x44\xd2\x42\x6b\x33\x64\xc8\xd3\x91\xc5\xa3\x1d\x99\x59\xa0\x98\x15\xf4\x64\xa5\xfd\x4a\xad\xea\xc9\x8a\x55\xc9\x11\x71\x93\xfa\xb3\xba\x30\xf2\x65\x78\x59\xaa\xab\xf3\x4c\xf6\xac\x89\x1d\xd8\x94\xc2\xb6\xef\x53\xed\x20\x48\x76\xdd\x87\xad\xb6\xaf\xe8\xa9\xcc\x01\x2e\x7b\x5e\xbf\x8c\xc2\x16\x34\xab\x1e\xd6\x6d\x6e\x02\x6b\x5e\xb6\x6b\xf6\xf8\x78\xd9\xc3\x3e\x36\x2b\x67\x7d\xdd\x97\xcb\x53\xd0\xbb\x6c\x2e\xe0\x36\xb9\xe7\xe3\x27\x95\x64\x9f\x47\x9d\xad\x8a\x27\x6d\x82\xa0\xac\xd3\x16\xba\xd4\x35\xa2\x3b\x00\xc9\xc8\xeb\x9b\x18\x8e\x8c\x35\x2e\x76\x7c\xce\x59\x2b\xb0\x9a\xe3\x4b\x29\xf4\x61\x1a\x9d\x69\x2b\x5a\x1b\xcf\x44\xe3\x90\x1d\xd7\xcd\x10\x7d\xec\x8e\x17\x9d\x51\x38\xb9\x76\xe6\x67\x15\x9c\x22\x26\xa8\xa9\x67\x12\xc4\x63\x4b\xc7\xec\x56\x00\x91\x61\x12\xc7\xe7\x13\x60\xd8\x2c\x2a\x7b\xbd\x4a\x8c\xdd\xa6\xbd\xcf\xd3\x3c\x37\x62\xb4\xac\xb1\xe7\xaf\xd8\x29\x35\x02\x1e\x61\xc0\x79\xb8\x6c\xa6\x61\xd9\xf6\x6d\x4f\x49\xb5\x11\x3d\x8c\x45\xda\xec\x68\x85\xcf\x6b\x25\xea\xd5\xf8\xa6\xdd\x8d\x37\x18\xdd\x09\x17\xee\x5c\x74\x12\x42\x00\x9d\xe2\x5c\x9a\x8e\xb7\x40\x4f\x6c\xdb\xc6\xc6\xd8\x12\x78\xb4\xc4\x17\x61\xd4\x83\xd4\x88\x59\xaa\x8d\xa8\x42\x93\x35\xde\x09\xa3\x74\x42\xcc\x9b\x86\xcc\x52\x11\x8b\xc4\x3c\x8d\x8a\xb4\x78\x2a\x39\x1a\x8f\x26\x14\x79\xc2\xdd\x3f\xc8\x9f\xd9\x89\xf9\xd3\x3a\xd1\xd9\x36\xfc\xbd\xd8\xac\x13\xd9\x8f\x35\xfb\x83\x29\x88\x6b\x6b\x1d\xdd\xa3\xa1\x6d\x19\xb5\xcc\xa9\xf1\x32\xf0\xa9\x43\x60\x2e\x86\x10\xb2\x43\xa4\x62\xee\x58\x9e\x4f\x54\x31\x35\x2b\xd5\xcc\x3a\xe8\xcf\xb8\xc3\x42\xf5\xa6\x43\x64\x38\x5a\x21\x32\xbc\x4d\x66\xbd\x96\x7c\x1b\x88\xd3\xb8\x67\x89\x00\x90\x34\xad\xb2\xc6\x03\x82\x62\xa2\x5d\xc2\x44\x97\xa9\xab\xaf\xc6\xe2\xe1\x93\x69\x87\xdf\x74\xef\x79\x22\x04\xa4\x38\x4f\xf3\x4e\xbb\xee\x85\xeb\xe7\x9b\xd2\x87\x87\x75\x89\x2c\xac\x94\x74\xdb\x21\xae\xda\x2e\xa3\x25\x2b\x75\x12\xa0\xf0\xfc\xfc\x6b\x89\x73\xae\x8e\x7d\x78\xd7\x1c\x27\x13\x3a\x52\xed\x3a\xae\x10\x42\x78\xbd\xc3\x95\x32\xc2\x20\xb6\x9c\x3c\x47\x32\x23\xbc\xff\xc5\xbe\xa6\x2c\x54\xba\x1a\xea\x9a\x01\x85\x83\x8d\x80\x4b\x8d\xd7\x2b\x8f\x69\xe0\x9b\xe7\xe9\x8f\x31\x86\x45\x55\x96\x73\xed\xdb\xae\xc6\x9d\x0c\x6f\x73\x12\x05\x02\x8d\x2f\xda\x1f\xdd\x58\x82\x60\x50\x8a\x7f\x06\xd4\xe4\xda\xb1\x72\x82\x49\x90\xd5\x35\x5e\x5d\x36\x11\x4e\x64\x3a\x8f\x23\x3a\xed\x90\xd3\xb4\x62\xdb\x3c\xb2\x3d\x7b\x6c\x02\xce\xd3\x30\xba\x60\x55\x70\x04\xf4\xb5\xf2\xc3\x63\x72\xab\x71\x1a\x5d\xbd\x15\x43\xb3\x8f\xfa\x36\x69\x74\x99\x40\x2a\x2b\xdd\x10\xe6\xcd\xfe\x2b\x8d\xf7\x27\x64\x25\xe7\xc8\x46\xbe\x9f\xb3\x6c\x15\x0f\xdb\x78\x7c\x9b\x03\xc7\x28\x91\xc5\xaa\x17\xec\xf6\x24\x43\xef\x61\xef\x93\x0c\x13\x56\x2f\x32\x4e\x5a\xc2\x03\xe9\xc6\xb3\xba\x41\x92\xbd\xef\x6f\xf7\x5f\x64\xf2\x2a\x67\xd0\x59\x75\xa8\x02\xfb\xbb\x41\x1a\xe6\x19\xd1\x7f\x31\x38\x49\xc7\x18\x03\x5f\x41\xab\xfc\x49\xda\x4c\x62\x95\x06\x79\x87\x3e\x23\xea\xee\x1a\x8a\xdf\xb6\xef\x11\xb5\x3f\x81\xb2\xe8\x11\x0b\x27\xbe\x65\x97\x23\x86\xad\x78\xdb\xc8\x87\x7c\xc8\xb8\xd1\x8e\xa5\x8d\x98\xb5\xe2\xfd\x26\x39\xb0\x93\x34\x13\x76\x99\xde\x90\xf6\xb4\xa5\x0d\x77\xcf\x0c\xb2\x26\x75\xa4\xe0\x85\x4f\xb4\x8d\x0c\xaa\x04\x4e\x2e\x37\x78\x32\xff\x08\x24\x10\x98\x28\xf7\x0d\x95\xe8\xe6\xb3\xf8\xe5\xcb\x6f\xdf\xbe\xf5\xbe\xfd\xd0\x2b\xab\xeb\x97\x67\x27\x2f\x4f\xff\xfa\xe7\x7e\xff\xe5\x98\xd3\xfc\x5f\x1f\xd2\x3a\x1f\x9e\xd2\x2d\x10\xbc\x06\x22\xe8\xf7\xfa\x81\xb2\x46\xbd\x6f\x9b\x82\x30\xfc\xbe\x8d\xb9\x9f\xd5\xf3\xde\x15\xd0\xb7\xf0\xe5\x7f\x87\xa8\x0f\xfa\x80\x8c\x67\xf4\xe2\x3c\x7d\xf1\x8f\xcb\x0b\xfc\xff\xb7\xd1\x65\xef\x6f\x2f\x2e\xfe\xf3\x3f\x5e\x46\xc2\x98\xf5\xc5\xb8\xd9\x65\x33\xc9\xcc\xf3\x33\x02\xc3\xea\x5b\xec\x94\x66\xda\x5f\xb2\x3b\xf5\x4a\x4c\x31\x3f\x4f\x26\xe5\xb7\x8f\xf0\x74\x4a\x04\x35\x4e\x1f\x16\x1c\x76\x56\xa5\x45\x4d\x2a\x37\xc3\xbb\x38\x85\x30\x95\x57\x7d\x57\x0c\x71\x03\x5d\xcc\x4b\xd4\x68\x40\xb9\x85\x8c\x81\x90\xe3\x49\x7a\x07\x91\xc3\x6c\x32\x39\x86\x65\x83\xfe\xc7\x59\xdb\x02\x02\x4e\x11\xa4\x50\x07\x40\xfd\x4e\x33\x34\x52\x26\xc8\x0c\xe0\x5f\x6b\x28\x99\xfc\x1b\x1f\xec\x61\x28\x3e\xf1\x95\xd3\x76\x0a\x67\x83\x61\x39\xa9\xa1\x72\x33\x7c\x80\x8c\x64\xed\x87\xd2\xd4\xd9\x7e\xd9\x1f\xb1\x23\x62\x2b\x50\xaa\x56\xa4\xf4\x56\x61\x4e\x54\x58\x59\x56\x23\xa9\x75\x30\xac\xca\xba\x3e\xaa\x72\xa5\x12\x27\x34\xc8\xb9\x20\x13\xd5\x1c\x2a\x92\x0a\xd8\xf0\xe8\x34\x32\xca\xa5\x2a\x01\x30\x62\x29\x31\xdf\xd8\x6d\xb0\x2d\x15\x68\x95\x00\x27\x8f\x51\x95\x5e\x5f\x9b\x4a\x40\x1f\xe2\x91\x89\x5f\x80\x88\x4d\x21\x2f\xfc\x61\x7f\x9f\xf2\x65\x5f\x26\xe2\x37\x69\xf9\xc4\x2f\x9f\xcb\xbf\xa6\x93\x9c\x54\x46\x16\x14\xc0\xd2\x01\x8c\x45\xb7\x50\x1f\x18\x16\x31\x15\x37\x59\x3a\xc2\xbd\x96\xca\xb9\x61\x58\x3e\x08\xcd\x47\x23\x39\xb2\x37\x10\x24\x63\xab\x6c\x6c\x9e\x3e\xa5\x6a\x5c\x50\x59\xf4\xa3\x52\xe4\xc0\x49\xbf\xff\xfb\x22\xbf\x95\xc7\xc4\xa1\x9a\x35\x39\x0c\x97\x98\xa4\x57\x4a\x95\x61\xa2\xbf\x47\x95\x00\x28\x73\x52\x96\x33\xea\x64\x98\x49\x1c\x31\x4d\x8b\x7c\x9c\x51\xe4\x14\x6a\x0f\x0c\x11\xd7\x4f\x46\x62\x08\xc3\x16\xca\x80\xef\xfa\x81\x3d\xc0\xe2\x77\xd9\x28\x4f\xd5\x2f\x23\x7b\x72\x1a\xee\x2b\x7e\x56\x03\x38\x45\x2b\x63\x98\x9d\x54\x8b\x29\xac\x37\x9e\x61\x05\x4e\x29\xd6\xa3\xb3\x3b\x15\x96\x52\x41\x3f\xf3\x7c\xba\x98\x72\x02\x60\xf7\x80\xf9\x93\xd9\x91\x12\xec\x4d\x39\x19\x29\x2d\x92\x59\x59\x6b\x8d\x9a\x59\x95\x4d\xb4\x96\x0a\xa1\xbd\x58\xb5\x03\x9e\x6a\x84\xd8\x6a\x54\x7c\xa5\x7a\xac\xca\xa0\x5f\x51\xfd\x08\xc2\x60\x9f\x80\x56\xa1\x22\x3c\xcd\x70\x78\x30\x33\xbc\x06\x9e\xfc\xaa\x94\x9d\x51\x0f\x4b\x35\x8b\xe8\x11\xbf\xae\x49\x3d\x45\xaf\xab\x3a\x4b\xa7\x88\xb6\x48\xc3\x5d\x93\xae\x8a\x6c\x79\x7d\x93\xea\x8f\x11\xbd\x11\x8b\xc2\x07\x48\x2a\x6a\x2c\x0f\x5e\x67\xb0\x4c\x77\x71\x3d\xca\x74\xd5\x50\x3f\xec\x95\x43\x18\x73\x78\xe0\x55\x4b\x7b\x3c\xb0\xca\xd0\x09\xb2\x9d\x04\xc9\x27\x75\x54\xd2\x2b\x86\x70\x90\x6f\x34\x59\xf9\x19\xb1\x20\xe5\xa3\x5e\x11\x28\x3c\x4c\x65\x2e\xcc\xa5\xd4\x0f\x43\x04\x46\xa5\x51\xff\x36\x2d\x47\xd8\x3f\x44\x70\xd2\x19\x2c\x6e\xc4\xc0\x33\x24\x67\xb7\xac\x90\x81\x97\x13\x73\x9e\x4d\x91\x30\x42\x7a\x7c\x3c\xa5\x0e\xc3\xae\xc0\x37\xb9\xbc\xf0\x91\x68\x0c\x3e\x9c\xc0\x32\x20\xa0\x04\xb6\x1a\xe1\xfa\x14\xdc\x71\xb4\x80\xd3\xa5\x68\x59\x4b\x2b\x82\xab\x88\x6c\xc0\xaf\x2f\x86\xfc\x1e\x58\xd4\x2b\xa0\xc7\x40\xaf\xab\x00\x96\x6f\x60\x2d\x2c\xda\x58\x5e\xe0\x64\xb8\x0d\xa8\x24\xc7\xfa\x1a\x0a\x72\x5b\x1d\xe0\xfb\x50\xbf\x07\x2e\x19\xe6\x58\xf9\x16\x38\xbd\x23\xa3\xe8\x85\x63\x58\x45\x8b\xc2\xc9\x71\x49\x60\x08\x38\x05\xc2\x8c\xbf\x0b\x34\xe9\x0a\xc8\x59\x18\x39\x42\xd6\x04\x23\xc0\x27\x5c\xfa\x81\x3d\xe9\x19\xee\x08\xa1\x5b\x67\x81\x3d\xa3\x02\x7a\x26\x6a\x1f\xa8\x09\x15\xc0\x2f\x6c\xc9\x81\x9a\x57\xf8\x8e\x1d\xe8\xc8\xc0\x47\x9d\x26\x25\x5d\x6a\xe7\xc8\x4c\x3d\x07\x74\x38\xba\x1f\x2a\xaf\xb9\xd2\xfb\x8b\xdc\x94\x3e\xe5\xc5\x57\xe5\x60\x48\x45\xd1\x0c\xc5\x88\xa8\x29\x15\xc7\x4b\xaa\x66\x46\x94\x1a\x78\x55\x27\x50\x29\x8f\x35\xe5\x28\xde\x1c\x64\x55\x9e\x90\x47\xaa\x8f\x30\x8d\x9a\xf6\x90\xda\x00\xed\x95\x6e\xb3\xe7\x52\x31\x94\x13\x44\x4d\x31\x84\xc9\xc0\xea\x85\xae\x2c\x64\x12\x66\x73\x16\x96\xca\x36\x8e\x95\x42\x43\x19\xb6\x05\x90\x93\xe4\x1e\x96\xd3\x9c\xf1\x7f\x15\x6a\x16\x3e\xe7\x0a\x2a\x58\x6e\x5b\xf0\x44\x13\x8a\x1e\x32\x85\x7a\xcc\xca\x76\x88\x5e\x3b\x4b\xee\x0f\xf3\xef\x40\xf5\xef\x67\xaa\xc4\xf8\xbe\xe9\x1b\xdd\x56\xdc\x5a\x9f\x93\x0e\xc8\xe4\x9c\xd1\xb8\x2e\x50\x7d\x47\x75\x26\x3e\x2b\x7a\x8d\xcf\x6a\x7f\x67\xa7\x0e\xe8\x4a\x59\xba\x51\x46\x9f\xea\x50\xde\x6d\x3e\xca\x46\x6b\xe9\xda\x6f\x54\xe0\x6f\x18\x34\x5b\x9b\x97\x10\x82\xbb\xf4\xda\x38\xcf\x26\xec\x53\xb9\x5c\xcc\xd7\xd2\x62\xed\x37\x55\xd0\x6f\x6b\x37\x24\x6c\xa9\x7a\x6b\x67\xd0\xdf\x90\x66\x32\x59\xab\xc8\xc2\x07\x3e\xc6\x2a\xbc\x28\xa1\x0e\x9c\x43\x6f\xed\x60\x4c\x2e\xdb\x39\xbf\x1a\x72\x83\x9f\xab\x6c\x0d\xb6\x35\xac\xde\x1a\xce\xeb\xdf\x46\x96\x29\xd8\x6f\xbd\xb5\x23\xf8\xa0\xfa\x96\xd7\x99\x58\x83\x4e\x5b\xcb\x72\x7c\xb7\x2b\x50\xc2\x9b\x6a\xeb\x6f\x3d\xf4\x77\xac\x38\xb1\x95\xfd\xf6\x2f\xe8\x2c\x59\xce\xbf\x45\x77\xed\xca\xba\xfc\xa1\x0e\xd3\x4a\xa0\x8b\x1e\xf6\xd9\x92\x4e\xd3\x7f\x6d\xcc\x3d\x4b\x61\xb0\xb1\x2c\xb7\xc3\x9c\xf0\x43\x5b\xcb\x95\xd7\x65\xec\x44\x50\xde\xbb\xad\x11\x6a\xe5\x6e\xad\x59\xd2\x5a\x30\xf9\xdb\xab\xb9\x51\x82\x8c\xa2\x32\x8e\x54\xa3\x9e\xd1\x84\xb4\x95\x95\x55\x7e\x6d\x22\x55\x87\xf9\x6c\x88\x1a\x54\x23\xee\xff\xf0\xca\x2f\x7e\x7f\x86\xdf\xf8\xb9\x51\xb2\x0c\x1d\xc3\x3f\x2a\x4c\xda\x1e\x92\xb0\x69\x1f\xe8\xc9\xdc\x86\x77\xfa\x17\x28\x32\xce\xab\x74\xf6\x81\xa5\xf3\x4d\x35\x00\x72\xf4\xc3\x52\x16\xbc\x38\x59\xc0\x21\x65\x64\x4c\xb1\x5a\xee\xc6\x06\xb5\xb9\x30\xcc\x7b\xcd\x7c\x15\x5e\x19\xcb\x2f\x26\xc0\x1f\x4c\x5c\xe1\x1b\x42\x9a\x75\xc5\xe1\xf5\x82\xd0\x4e\xd1\x7e\x85\x85\xf5\xa5\x98\x7a\xfd\xa2\xf9\xbe\x26\x79\xf4\xaa\xac\x3d\x90\x40\x9d\x7d\x1f\xff\xfc\xe3\xbf\x4a\xc3\xea\x31\xbc\xe2\x27\xd8\x2b\x35\xf5\x9d\xcb\x96\xb1\x51\xea\xd8\xe0\xf0\x49\xef\x69\x66\x38\xa5\x7b\xcb\xad\xfd\x30\xca\x5d\x75\x90\x6e\x6c\xac\xa7\xb0\x5a\x86\xa8\xe5\x8f\x1a\x77\xea\x39\xc9\x23\x17\x66\x29\x5d\x25\x7e\xf6\x2a\x01\xff\xfc\x1c\x40\x5c\x69\x3b\x2d\x59\x8f\x68\x7e\x03\xc3\xb6\x86\xa4\x1d\xdb\x2c\xc9\xbb\x23\xfd\x5a\xe3\x16\xac\x0d\xd3\xa2\x28\xe7\x48\x75\xf1\x5b\xa4\x9d\x46\x5e\x1c\x59\xc0\xc4\xda\x79\xa5\xa8\xda\x4e\x08\x5d\x45\x09\x18\x98\xfe\x20\x7f\x07\xf9\x93\x08\x47\xeb\x32\xe6\x4a\x8f\xb1\x4c\x74\x9c\xc4\xe6\xc6\xb2\xd7\x93\x52\xf5\xaf\x2c\xac\x34\x15\xa8\x51\x27\x23\x8d\x2a\x56\x32\x82\x63\x0d\xd9\xa1\xa3\xbf\x71\xf4\x51\x1b\x59\x0e\xd9\x5d\xa1\x1f\xf6\xe3\xd3\xf0\xed\x5a\x84\x21\x77\xb4\x9a\xe5\x75\x33\x2c\x21\xd6\x00\x52\x3e\x82\x51\x7a\xa8\x4c\x41\xa5\xd2\x43\x23\x72\x56\xce\x8c\xa7\x2c\xa9\x25\x85\xf6\x99\x96\x87\x2c\x18\x27\x52\x43\x86\xb9\xeb\x53\x4e\x55\xa5\x16\xdd\xa5\xa2\x00\xb7\xbb\xd4\x82\x4b\xad\xe8\x5e\x48\x54\x76\xb9\x5c\x10\x22\xc9\x74\x98\x14\xc8\xb2\xab\xee\xb2\xf3\xa4\x5a\x51\xb6\x1c\xb2\x5c\x70\xb6\x22\xb7\x4b\x57\x17\xaf\x08\x62\xd3\x5c\x84\x1a\x26\x52\xd7\xa1\xec\xae\x03\xba\x62\xef\xae\x43\xa9\xa6\x8d\xc9\x5a\xa4\x76\x3d\x4a\xab\x50\x84\xd1\xea\x18\x79\xa8\xae\xed\x1c\x9a\x34\x3b\x0c\x72\x36\x5d\x0b\xea\xb7\x10\xe5\xcf\x9e\xfa\xbe\xcb\xa0\x6e\xe5\x04\x1d\x33\xa0\xdb\x42\xb7\xd2\x8c\x54\x8e\x0a\x7f\xfd\x2d\x94\xc6\x8a\x99\x7f\x42\x98\x81\xb5\xbf\x47\x83\xef\xc2\x58\xa1\x21\x9c\xca\x04\x02\x54\x71\x08\xfd\xa2\x5f\x10\x49\xbf\x50\x2a\xf0\xc9\x02\x26\x23\xea\xbe\xdb\x12\xf4\x78\x06\x7c\x53\xb6\x23\x57\x2a\x65\x89\x5e\x21\xe6\xdf\xca\x46\x58\x29\x80\xdc\x64\xcd\x94\xa9\x18\xe7\xb7\xcd\xc0\xda\xa3\xdb\xdb\xda\x14\x7e\x7e\x4c\x67\xca\x6f\xfd\xf0\x45\x3b\x25\x37\x9c\x03\x59\x43\x03\xff\xd9\x40\x83\xd4\xce\x6e\x1b\xe6\xab\xea\x06\xa8\x76\xd2\x92\x60\xd2\x00\x04\x70\x28\x6b\xff\x1c\xa1\x35\xa4\x39\x38\x51\x94\x41\xcf\x9d\x48\x1c\x18\x3b\x58\xca\xb2\xc8\xd8\xcd\x44\x02\x03\x81\x1e\x2b\x66\x89\x13\xc4\x77\x10\xa6\xaa\x63\x3b\x9a\xd9\xe2\x03\x25\x64\x37\xd7\xb4\x14\xed\x5e\x15\x5b\xca\x25\x8e\x99\xee\xad\x7d\x0e\xcc\xaa\xb1\xf1\x04\xd7\x3a\x1a\x5e\x5b\xe1\x27\x19\x7a\x41\xce\x27\xd4\xf4\x3b\x2b\xe2\x34\xab\x6e\xb3\x8a\x01\x10\x18\xf8\xe6\xd2\x7f\x97\x26\x31\x8f\x61\x9b\x19\x49\xde\xc9\xc0\x1d\xe3\x01\x81\xc6\x0d\xf7\x1f\x79\x8b\x10\x32\x53\xf5\x3d\x19\xba\x77\x9f\xe2\x9b\x0e\xf9\x98\xe2\xaa\xbb\x13\xbb\x18\x32\x81\x2e\x53\x49\xd0\x5f\xdb\x14\x66\x39\x5d\x0f\x50\x35\x03\x11\xf0\x99\x24\x10\xa3\x1e\x3f\x21\xd4\xf1\xbd\x9a\x2d\xf1\xfd\x34\x45\x2c\x4f\xf8\x2f\x24\x37\x03\x6f\xf2\x09\x78\x30\x36\x07\xa1\x5f\x81\xb5\x8d\xf7\x97\x42\x8f\x13\x2c\x07\xbc\x86\x9d\x08\xdd\x7b\xf1\x54\xe4\x45\x3e\xcf\x49\x12\x64\x2b\xb7\x38\x8c\x7b\xcf\xd5\x7c\x41\xa3\x11\x6e\x18\x4d\xca\x38\xed\x59\x6f\xc2\xe9\x84\xf8\xbb\xb0\x1b\x1c\xef\x0a\xa7\x47\xe2\x6f\x0a\x3a\x88\x8e\xdf\xbe\xd3\x02\x32\x96\xd2\x2e\x66\x07\x7d\xfb\x14\xe4\x97\x47\x35\x68\xd4\x5b\x11\xbb\xea\xcb\x0f\x77\x07\x7b\xab\xbf\xc6\x14\xc2\x9a\x05\xf1\x95\xe0\xf1\x88\x4f\xe4\xc3\x99\xf4\x6f\x1c\xdf\xf5\xdc\x00\x2b\x3e\x45\x83\x54\x06\x5a\xb0\x53\x99\x60\xb1\x60\x56\x59\x97\xbb\x43\xca\x7d\x50\x37\x7f\x84\xc8\x6b\x5a\xa7\xaa\x47\x87\x3d\x37\x40\xe0\xd9\x57\x12\x86\xb8\xee\x59\x6f\xe2\xf2\xb2\x9e\xe1\xe1\x33\xbe\x5c\x0e\x7c\x57\xef\x97\x97\x27\xfb\x3b\xbb\x67\x97\x7b\xfb\x7f\x3d\x3b\x3a\xfa\x74\x7a\xf9\xe7\x4f\x47\x1f\x76\x3e\x5d\xfe\x72\x74\xf4\x97\xcb\x4b\xaf\xbf\xe0\xd5\x9f\xc8\x15\xb2\xb1\xf1\xa4\x64\xe1\xbd\x4d\xb9\xe2\x85\x68\x10\x8a\xf8\x46\xb0\x7a\xd9\x48\x98\x55\x1e\x5f\x0b\x87\x14\xc5\xb3\x65\x34\x38\x55\x1e\x8b\x93\x60\xab\xd7\xff\xa1\xf7\x43\x60\xdd\xb7\x9e\xb6\xcc\x36\x1c\xdb\x8c\x55\x30\x14\xde\x3b\x5a\x97\x98\xc7\x3f\xbf\x16\x2e\xc9\x8e\xd9\x4f\x4a\x83\xb8\xc7\x3f\xff\x2c\x9a\x64\x3c\x66\x04\xe4\x36\x11\x8f\xdf\x1a\xa3\x67\x24\xc7\xf1\xdb\x1f\x45\x27\x2d\x8e\xfb\x5b\x06\x27\xb5\x45\x8a\x21\xd6\x14\x6c\xb0\x97\xfb\xfd\x66\xa0\xd9\x0c\x20\xd6\xd4\xab\x49\xbc\xe3\xfe\xab\xad\x0e\x83\x6c\x43\xba\x21\xe4\xad\x68\x53\x6e\x75\x3c\x6f\x12\x6e\x08\x37\x2d\x68\xd2\x6d\x88\xa4\x06\xd8\xf4\x19\xce\x70\x54\x7f\x43\x9e\xe3\xfe\x5b\x3a\xa7\x3c\xa6\x66\x67\x6d\xd7\x2e\xc1\xcf\x09\x8b\x5c\x2d\x7d\x0f\x8c\xb4\x44\x22\xf7\xb9\xf0\x6e\xd4\x0c\xeb\xf1\x1c\xe8\x39\x5d\xc6\x23\x67\x19\x69\xd4\x20\x6e\x23\xc2\x5e\xba\xbd\x48\x6e\x36\x37\xc5\xec\x1c\x1f\xc9\x32\x4d\x3d\x3b\x68\x45\xcd\x93\x6a\xd9\x62\x56\x58\xb1\x2a\x5d\x65\xc2\x69\x33\x21\xf6\xf1\x9b\xc8\xb8\x61\x47\x94\xd6\xcd\x61\x86\xcd\xb4\xa4\xb8\xcd\x3d\x77\xd2\xe9\x01\x60\x86\x36\x26\x63\xf4\x8f\x88\x2e\x65\x46\x89\x36\xaf\x0f\xae\xe0\x7f\x60\x19\xd8\x2b\x8c\x7b\x63\x64\x1f\xd0\x71\x37\xf0\xd8\xd9\x07\x96\x67\x49\x98\x59\xcd\x24\x6c\x2a\x6d\x27\xa2\xab\xaa\x66\x32\x69\x81\x6f\xa7\x63\x04\xed\xa0\x69\x90\x1f\xc8\x2b\x64\x58\x58\x8b\x40\x5b\xe6\x43\xe8\xec\x2e\x50\xb6\xf9\x01\x90\x9d\xa0\x69\x9c\x1f\x8c\xae\x26\xa6\x15\x64\xa2\x1f\xe0\xc5\xb0\x7e\xa5\xd6\x60\x88\x6a\x86\x31\xd4\x97\xc1\x84\xe3\x60\xdb\xeb\x73\xf8\xf7\x7c\xae\x83\xd9\x6a\x9f\xc2\x25\xa6\x84\x6d\xbc\x4f\xe1\xe5\xad\x95\x8d\xec\x1f\x0c\x37\x1d\x43\x96\xfc\x10\x56\xce\x02\x63\xbd\x1f\xc8\x6b\x21\x6d\xc0\x2f\x5d\x05\xd8\x36\xfc\xc1\xd7\xec\x0e\xef\xbd\x55\x20\x1b\xf2\x63\xe8\x0c\x9f\x54\xf0\x97\x19\x85\x2d\x38\x7b\x63\xc4\xcf\x78\x15\x3a\x03\x63\xcb\xcf\x11\x28\xb7\x33\x11\x68\xd2\xcf\xe1\xa5\xac\x85\x31\xec\x97\xe1\xaa\xa1\xca\xbe\x9f\x83\x65\xb1\x6c\xe4\x1f\xcc\xf0\x27\xb0\x2c\xfb\x03\xbe\x42\x0d\x7c\xd6\xfd\x41\xad\x02\xac\x19\x6a\x6c\xfb\x83\xb9\x7a\x0c\x9a\x26\xfe\xc1\x1c\x5f\x86\xf4\x62\x22\x69\xc8\x29\x46\x8d\xb9\xb1\xf8\xe7\x70\xdd\x66\xcb\xf0\x9f\x63\xcc\x70\x31\x00\x40\xf0\x0d\x7f\x82\x25\xb0\xdb\xc1\x25\x21\xb2\x6a\xc9\xdb\xc1\x5e\xb0\xc9\xec\x4c\x78\x98\xce\x6f\x7a\x15\x50\xfc\x72\x1a\x46\x91\x54\x77\x7a\x85\x0c\xf9\x30\x44\x90\x57\x71\x6f\x28\x81\x36\x65\xb5\xb4\xc2\x73\x63\xb0\xec\x49\xe8\xd8\x79\x22\x42\x1f\xef\x2d\x67\x52\x4e\x16\x4e\x7b\x37\x4e\x00\x94\xdb\x6b\x67\x43\x0a\xe6\x68\xfc\x53\xb0\x36\x85\x9d\xab\x2f\xfd\xc6\x86\x2f\xb4\x67\x72\xa0\xc3\x2e\x2a\xa7\x37\xf2\xd3\x77\x19\xe1\xba\x2f\x87\x87\x07\x6f\x70\x4f\xe7\x14\xa2\x01\x2b\xa3\x1e\xc0\x41\xb6\x03\x4f\x3f\xc9\x48\x01\xbb\x40\x52\x9b\x3e\x66\xc3\x47\xaa\x55\x4d\x0c\xa3\x2d\x20\x9d\x5a\xbc\x35\x7b\x3f\x1c\x0c\x95\x88\x6b\x9c\x20\xf0\xef\xa0\x6c\xda\x10\x8d\xa3\x8d\x8d\xf2\x7c\x8c\xb6\xcd\x63\x85\x83\x43\xb3\x64\x7b\x12\xca\x79\x12\x6d\x7b\xdb\xd6\x12\x26\x9b\x6f\x85\xfc\x12\xcd\x18\x20\x1b\x5a\x4b\x7f\x3c\x2f\xeb\x73\xcc\xf0\xf9\x19\x20\x02\x39\xe6\x71\x2a\x97\x2b\x64\xa2\xdb\xca\x61\xd8\x58\xb5\x98\xd7\xb7\x56\x54\x52\xfa\x82\xb1\x0b\xe1\x1c\x84\xfe\xfe\x79\x55\x6c\x7e\xed\xfd\xf4\xd7\x83\xcf\x7b\x47\xbf\x5e\xfe\xb2\xf3\x79\xef\xd3\xbe\x55\x79\x22\xb7\x0f\x0f\xfa\x1d\xf7\xc8\xed\x10\xda\x22\x09\x30\x36\x25\x7c\x4e\x5b\xd8\x4d\x8d\xfa\xbc\xf0\x2f\xba\xae\x8f\xc9\x09\x8e\xdc\xa1\xd1\x17\x93\xaa\x07\x32\x07\x1b\x1b\xdd\xf5\x68\x77\x8a\x5d\x0d\xf8\x7a\x65\x45\xda\x5f\x73\x3d\xe8\x63\xa2\xf7\x68\x2a\x5c\x9e\xeb\x28\x84\x78\x57\xef\x54\x10\x06\x44\x70\xf4\xf2\xac\x8c\xa7\x95\x3a\x16\x23\x58\x41\x58\x4b\x5c\x49\x64\xd7\xb9\x14\x2b\xef\x70\x2c\x34\x90\xa7\x15\xa1\xa4\x92\xad\xae\x7f\x76\xb6\xee\xc0\xa9\x7c\xb3\x02\xc5\x11\x3c\x19\xe9\x1e\xf2\xb0\x2c\x72\x38\x07\xe0\x41\xd7\x55\xf0\x5d\x1f\x2b\x63\xfb\x05\x90\xa8\x31\x6c\xd6\x37\xd6\x67\xf5\xc0\x5b\xf0\x94\x73\xb3\x12\xa2\xe0\x1e\x38\x3c\xf4\x12\xd8\x69\x3e\x5c\x3e\x1f\xfe\xa1\x7c\x12\xfc\x43\xd9\xb3\xde\x1c\x08\x87\xd2\xb1\x06\x68\xe0\x34\x94\x3d\x37\xc0\x87\xc7\xa0\xd2\xd8\x81\x0e\xce\xe9\xf4\x8f\x7a\xec\xf1\x82\x0d\x74\x1f\x4e\xdb\x1c\x3a\x1c\xe9\xe8\x84\xd5\x64\xd0\xe3\xfe\x4f\x3f\x77\x3a\xee\xc1\x73\xcc\x63\xaa\xf0\xd6\x79\xaa\x2d\x8e\x93\x47\x90\xf1\x04\x95\xe2\x8a\xb6\xfc\x93\xe5\xc5\xf3\x5c\xb9\xf1\xf1\x88\x42\xf9\x22\x9e\x19\xef\x56\x1a\x74\x15\x6c\xb2\xd0\x12\x33\xff\xe5\x01\xde\x39\xeb\x2b\x9c\xb4\xdb\xe0\x3f\xb5\x0c\xfe\x53\xdc\x6a\xd1\xe4\x1f\x79\x1b\x04\xfe\x48\x2f\x92\x85\x92\xd5\x57\x4b\xe9\x3f\xa7\xa3\x60\x21\xfd\x40\xc1\x66\x2d\xbd\xc7\xac\x2f\xd0\xd2\xb1\x85\x13\x37\xa4\x6a\x0d\xd9\x3a\x19\x92\x79\x1c\x32\x28\xcc\x0d\x34\xf7\x81\xbd\x1c\xb6\xfa\xc9\xc6\xc6\xa4\x77\x29\x0d\x3f\x95\x28\x68\x9c\xa0\xe3\x06\x86\x73\x98\x89\x71\x14\x21\x24\xca\x30\xcb\x6f\x33\xdd\x6d\xe1\x44\x8c\xa9\x6e\x62\xc1\x5e\x24\x08\x51\x0f\x72\xab\x5a\xf2\x27\x48\x3a\x64\x59\xe7\x0d\x74\xc2\x58\x76\x02\x7d\x76\xb3\x5c\xea\x3a\xcf\xa3\xf5\x96\x81\xfc\x10\x8e\xa8\xd0\x58\x4f\x4b\x10\x47\xaf\x55\x10\xb6\x49\x5f\x90\x2c\x96\x5a\x44\xd6\xee\xd8\x06\xd2\xc9\x5c\xdf\x42\x10\xd6\x4a\x3b\xe7\xa2\x71\xf5\x59\x5b\xd7\xc9\x1e\x09\x44\x73\xaa\xc2\x71\x5e\x2a\x14\x74\xcd\xd4\xb8\xcf\x82\x9d\x15\x13\x35\x7e\xb5\x85\x30\x74\x3f\x3f\xa6\xaa\xdf\xbc\x43\xa5\x3b\x72\x29\xe9\x55\x17\xb2\xca\xc4\x44\x06\xcb\x33\x67\x92\xb5\xac\xfd\xf0\xe2\x58\x8a\x01\x06\x79\x33\x17\x79\x0d\xd6\xc8\x45\x64\x8e\xd9\xa0\xc6\xa4\xb0\xee\x72\x95\x90\x76\xc0\x97\x61\x95\x05\x33\x48\xda\x04\xe8\xd9\x31\x47\x7b\x40\x83\x68\x54\xfa\xcc\xee\xa8\x0d\xd3\x14\x51\xd3\x16\x13\x6d\x37\x03\x01\xba\x9d\x99\x0e\x52\x6d\x2c\x5a\x16\xd3\x56\x1b\xc9\x32\x44\x67\x08\xd4\x63\xbd\xc5\xee\xb2\x73\xb6\x54\xad\xee\xdc\x2e\x4e\x75\x88\x29\x8e\x3a\x63\x50\x22\x60\x43\xbd\x6c\xd8\x52\xaf\xea\x14\xf4\x6f\x00\x84\x2f\xb5\x7a\xa6\x62\x4d\x0b\x99\x0c\xbb\x88\xac\xfd\x52\xdd\x45\xf0\x32\x96\x22\xf5\xb0\xf2\x5b\xdf\x75\xd9\x32\x5b\x6e\x0b\x30\xe3\x21\x2f\x52\xdb\xb2\xce\xb5\x27\xb2\xaf\x6d\x3e\xc2\x71\x5e\xde\x0e\xc9\xeb\x1a\x65\xc3\xb7\x83\xfa\x97\x9a\x5a\x8f\x5a\x2e\x04\x66\xbd\xd6\xcd\x1b\x5b\xd9\x79\x2e\xdf\x06\xb3\x86\x2d\x8c\x18\x61\x06\x4e\x58\x2a\x6e\x99\xd0\x4c\x93\x7b\x75\xc9\x51\x0a\xbc\xf8\x58\xc8\x2b\x8e\xc9\xb2\xbd\x8f\x7a\x8c\x65\xdc\x76\xc1\xae\x47\xa2\x58\x5f\xb3\x60\x51\xfa\x9c\x56\xff\xfc\x1c\x15\x50\x73\x09\xba\xdb\x06\xb2\xde\xde\x05\x92\xc4\x96\xdc\xa7\x3e\xd8\x78\x98\x90\xc0\xbb\x7f\xef\xa1\x31\xca\x09\x1a\xbe\x7c\xd8\x39\xdd\xc7\x4b\xdc\x15\x69\xf7\xf6\x3f\x1e\x7c\xde\xbf\x3c\xdc\xf9\xfc\xbf\x1f\x1e\x5a\x41\x97\x87\xfb\x27\x7f\xde\xdf\x6b\x5a\xfe\xd2\x5c\x85\xff\x77\xa1\x91\xe7\xeb\x2b\x80\x2c\x12\x77\x88\x43\xed\xde\x29\x68\x9b\xf4\x22\xb1\xc4\x91\x83\x16\xaa\xc5\x3e\xd4\xed\xa4\x37\x45\x16\x83\x96\xa4\x7c\x8c\x9e\xe6\x64\x7d\x63\x23\x5f\x4f\x92\x7d\x75\xb3\x9e\x49\xfd\x0b\x38\x05\xe3\xf2\x38\xf1\x20\xf1\x9c\x40\x12\xb2\x50\xb5\x5d\x0c\xb4\xfa\x3e\x47\xb1\x63\x0b\x5a\x3c\x47\xa9\x63\x09\x27\xde\xde\x25\x0b\x3e\xf6\x60\xa1\x7f\xc8\x8b\x11\x6c\xa6\x9e\x8b\x8e\x12\xd6\xc4\x0c\x35\x6a\xe0\x6f\x08\x7f\x84\x64\x7b\x13\x15\xea\xeb\x9d\xc5\xbc\xc4\xaf\x0f\xd3\x19\xdd\x65\xb7\x83\x49\x22\xeb\x8b\x40\xef\xee\x25\x41\x43\x24\xa5\x86\xfe\x1f\x4a\xe0\xf3\x64\x17\xbb\x01\xd8\x10\xc2\x12\xf7\x8f\xf0\xc3\x43\x2b\x26\xc2\x65\xea\x4f\xbd\x4d\x25\xd5\x21\x61\x51\x94\x70\xda\x69\xa6\x23\xed\x15\x48\xb2\x50\x49\xa2\xa5\x71\x43\x5f\x2e\x6d\xc0\xa6\xd2\x9a\x50\x0d\xc8\x13\x65\xaf\x8e\x86\xe8\xbe\xf1\x36\x98\x39\xf4\xc1\x09\xb4\x71\x3d\x8f\xe4\x46\xc2\x58\x3b\x18\x04\x7b\x07\x62\xea\x24\x95\x5d\xac\xc4\xf1\xb8\x0b\x81\xff\x41\xe7\xd9\x25\xb1\xbe\x66\xb0\xe6\x9e\x30\xcb\x35\xd8\x2a\x50\x96\xf0\x2e\x64\x83\x3f\xc4\x51\x27\x90\x1e\x2a\x9e\x9d\x9b\xeb\x3b\x49\x77\xe7\xd1\x24\xb7\x01\x42\x86\xab\x25\x9d\xcd\x26\x77\xec\x8c\x54\x2b\x16\xa1\x9e\x52\xe6\x8f\x19\xe8\x7d\xa4\xd0\x10\x37\x26\xcc\xa0\x22\x0f\xb8\xeb\xee\x97\xaa\x4e\x69\x98\xe3\xa9\x13\x7f\x2a\x54\x64\x69\xc1\x7d\xb4\xab\xd8\x55\xb9\x8e\xaa\x2d\x1b\x1b\x91\x51\x29\x22\x73\x33\x83\x9d\x51\x34\xac\xbb\x5d\x0e\xcd\xb3\x00\x18\x53\xa9\x1d\xde\xe5\x0d\x80\x30\x34\xda\xcb\x08\x38\x3e\x64\xfb\x10\xc7\x43\xdc\xf4\xae\x17\x69\x45\x60\xf3\x0e\xae\x22\x5a\xbd\x4f\x52\x32\x8c\xd8\x0c\x7a\xc1\x66\x86\x26\xf4\xd6\xee\xd8\x3a\x53\x8c\x6d\x3d\x89\x86\x66\x85\x47\xaf\xc2\xd5\x74\x20\xe5\x36\xa5\xfb\x31\xf2\xa8\x40\x1c\x92\x77\x07\x5b\xd5\xe1\x53\x3e\xce\x76\xef\x86\x93\x8c\xf4\x1d\xc2\xb6\xc2\xc3\xa7\x72\x48\x07\xda\xda\xa9\x40\x33\x96\x2c\x3f\x9c\x14\xcc\x8a\x12\x58\x1e\x56\xf3\xda\x7f\x11\x73\xd7\xd6\x35\xbb\x6c\x23\x21\x5f\xb9\x10\xea\xfb\x2d\x86\xe0\x2a\xbc\x67\xd2\x2f\x11\x66\xd1\x23\xf4\x65\x78\x2f\x89\xcc\xd1\xe7\xdd\x7d\x16\x0f\x5b\x54\x87\x03\x9c\xdd\xaf\x95\x46\x52\x30\x05\x5b\xfb\x0d\x95\x8a\x76\x13\x55\x94\x43\xc4\xd0\xb8\x08\xe1\xec\x1b\xa1\x46\xbf\xdf\x0d\x97\xf7\x33\xde\x28\x64\x11\x76\xbb\xe3\x8d\x07\x15\x1c\x84\x46\xac\xac\x31\x63\x6c\x92\x9e\x05\xde\xfd\x67\x9d\x89\x76\xad\xc2\xfc\x89\xa4\x0e\x82\x8e\xc3\xce\x74\x75\x6f\xf9\x92\xbc\xd9\x3e\x99\x60\x2f\x1f\xad\x8c\xc7\x0c\x4e\xf8\x8c\xe8\x69\x8e\xe0\x63\x8d\x5e\x20\xf2\x06\x6c\x45\x65\x9a\x29\x5a\xb5\x59\x9d\xc0\xd6\x25\x76\x93\xc8\xb3\xb6\xbe\xf7\x6f\x70\x4e\x4b\x71\x92\xdc\x5b\xab\xbd\x21\x68\x9f\xdb\x94\x00\x8e\x4b\x42\xce\x21\x37\x95\xbb\xaf\x25\x5b\x83\x42\x63\x14\x0d\x0a\x04\x22\xc2\x64\xb8\x33\x2c\x3d\xb3\xa4\x59\x60\x2b\x45\x72\x8d\x97\x27\x9e\x08\x52\x7a\x1c\xae\xcc\xcb\x97\x4d\x33\x87\xe6\xc4\x6c\x66\xd2\x88\x4f\x5a\x21\xdb\xb0\xbb\x35\xc3\xe0\xd3\x38\x5b\x5a\xeb\xa8\x99\xab\x8e\x51\xf5\xd2\x01\x54\x29\xb5\x2c\xdd\xcf\x98\x8f\x58\x2e\x51\xd3\x49\x3a\x0b\xe1\x75\xe2\x26\x9b\xf6\x24\x42\xe8\x89\x95\x46\x79\xfa\x16\x19\x0a\x69\x65\x82\x5d\x69\x80\xcf\x91\x19\xdd\xe4\x48\x15\xf9\x36\x54\xe8\x08\x1b\xc9\xf7\xf9\x7a\x8b\x67\x9f\x04\xb7\x0a\x4a\x6b\x72\x47\x5f\x03\x75\x53\xa4\x9b\x2e\x9b\x7c\x1d\xab\xeb\x70\x2a\xe3\x9f\x58\x41\xd9\xee\x95\x59\x9e\x58\x69\x9e\x96\xed\x52\x1c\x26\x56\x83\x97\x83\xeb\xf0\xd0\x82\x82\xb0\x4c\xc7\xc5\x29\x73\x5f\x47\xca\x95\x36\x2b\x77\xb5\xd5\x4d\x1b\x23\x4e\x9a\xfb\xad\xdd\x78\x63\x43\xfa\x6a\x17\xc6\x16\x4c\x9d\xeb\x87\x4a\x4a\xc1\xaf\x38\x25\xb2\x44\x8b\xbf\x8c\xe9\x82\x4d\x31\xb7\x7d\x81\xa1\x84\xc6\x82\xa3\x4c\x93\xdd\x2b\x80\x47\x6f\x01\xb7\x39\xe5\xe1\x09\x52\x37\x3e\x41\x4d\xdb\x43\x61\x85\xd8\x6c\x03\xd4\xf4\x9b\x12\x8e\x84\x39\xf3\x3b\xac\xaa\x1f\xa1\xff\xcc\x8c\x46\xa1\xb9\x52\x10\x1a\x5a\xb9\x9f\xe0\x05\xd6\x4a\x12\x46\x78\xdc\xb2\x0b\x95\x1a\x7f\x2e\xab\xba\x1b\x59\x49\xc8\xb1\x78\xe8\x06\x24\x52\x1e\xa9\xf4\xb8\xa9\x45\x99\xc8\x96\xed\xfb\xd7\xb6\xa2\xdd\x37\xad\xda\xeb\x48\xc6\x8e\x56\xc0\x52\xac\xd2\x65\xea\xd2\x5b\xf2\xeb\x1a\x19\x06\x09\xc2\x7f\x6c\x69\x19\x1d\x92\xe7\x9e\x57\xe6\x03\xc3\x1e\x41\xf0\xab\x96\x4e\x91\xcb\xfe\xc4\xfd\x1f\xb6\x3a\x93\x50\xb4\xc9\xd8\x66\x8f\xe2\xfe\x8f\x5b\x7e\x37\xd2\x2e\xde\xbd\xeb\x59\xc2\x27\x3d\x78\x8e\x99\x91\x5e\x4c\xfe\xb5\xb2\x54\xa2\x2d\x3f\x47\x67\x64\xe8\x9a\x73\x1b\xb8\x4c\xd9\xd2\x82\x80\xc1\x6b\x6e\x5a\x41\x49\x93\x0e\xb7\xcf\x52\x5e\x30\xec\xb9\xb6\x68\x25\xac\x73\x4d\xf0\x5a\x14\x39\x5f\x41\xf0\xac\xfa\xc0\x7c\x1f\x66\xdc\x20\x17\xb0\x5d\x7d\xfe\xd1\x24\x50\x74\xa5\x33\x73\x98\xca\x83\x16\xbe\xca\x33\x46\xb9\x39\x8a\xcf\x30\x04\x52\x2a\x79\x07\x7b\x47\x70\x66\xd1\x8c\xba\x3d\x6c\x4a\xc1\xb9\x4c\xee\x25\x8c\xb5\x12\x42\x71\xed\x10\xb8\xdc\x72\xda\x75\xec\x4d\xa3\x76\x0b\xd7\x97\x17\x29\xb5\x56\xbd\xc7\x5c\x7e\x91\x66\xab\x14\x8d\x1f\xec\xa1\x43\x2d\x4b\xd7\x31\x76\xbb\x9f\xd0\xb2\x0f\xf6\xc2\x86\xcf\xae\xd2\xea\xd4\x66\x73\xe3\xb7\x86\x1c\x18\x8d\x40\xe8\xc8\xb7\xcf\x70\x1d\xe0\x5a\xbb\xac\xf7\xb1\xbb\x3a\xab\x2c\xd1\x10\xba\x7a\x44\xe2\x2b\x78\xfb\xda\xaf\xa5\xd2\xd5\x1f\x15\xca\x28\x44\xd9\xeb\xaa\x09\xf0\x50\x5d\x51\xa2\xec\x75\xd6\x30\x99\x77\xc7\xc1\x77\xfe\xaa\xb3\x28\xce\x37\x37\x72\xba\x4c\xf5\x0c\x57\xcb\x9c\xe1\xed\x33\x50\xc4\x6d\x5c\x4b\xf7\x9e\xa9\x77\x49\x9e\x97\x24\x66\x30\x4b\x17\x95\x6c\x00\xb1\x4a\x81\x18\xb3\xd3\x74\x25\xd3\x08\xd6\xc8\x08\x95\x0c\x6c\xa5\x05\x2e\xe3\x6f\xac\x01\x69\xf9\x2d\xd8\x2c\x36\x83\xdf\x7a\xc1\x52\x79\x7a\x6d\x19\x5d\xea\xad\xc7\xeb\x72\xb1\x61\x1a\xe1\x18\x51\xb8\x07\x78\x47\x8d\x51\x9b\x46\x2c\x9e\x6c\x1a\xe1\x1c\xe3\x5d\x4b\x0b\xfb\x1c\x3f\xb1\xc2\x3f\xa7\x73\xfb\xfa\x2d\x70\x0d\x2b\xa4\xa1\x83\x2d\x95\xf7\x9d\xfb\x6f\x56\x09\x06\xda\x47\x7f\xfb\x12\xd6\x95\x43\xc8\x19\x63\x64\x10\x4d\x79\xc0\xd4\xb2\x63\xe4\x38\x63\x6f\x61\x2f\xd1\xbb\x27\x5c\xcf\x5e\xb6\xc4\x04\x7d\x14\x25\xdc\x6b\x46\xcb\xd5\x04\x23\xbe\xd2\x9d\x68\x1a\x50\x0d\xb1\xc7\x70\xa9\xc0\xd2\x61\x1c\x10\x0a\x55\xf6\x46\x76\x18\x2a\x4a\x41\x61\x2a\x83\x76\x0c\xed\x58\xb4\x23\x78\x22\xed\x73\x06\x12\x21\x27\xd2\xda\x92\x4c\x1c\x4f\xe7\xcc\x1c\x91\xed\x5c\xd5\x66\x6e\x05\x11\xb1\x20\x18\xd2\x64\x4b\x35\xa3\x56\x9a\x6e\xad\x22\xd5\x3e\x27\xd1\x78\x85\x7b\xbb\xd9\xba\xe9\x6e\x94\xda\x2e\xf2\x72\x73\xb3\xdd\xa3\x1a\x2d\x9f\x4b\x66\x1a\x63\x8e\x1c\xad\xd5\x4f\xfc\x4a\xa4\xc0\xd9\xd4\x07\x72\x01\xfa\x3f\x51\x75\xc2\x35\x3b\x41\x1a\xa1\xdb\x40\x87\x0e\xc4\x3c\x57\x7e\xbf\x3d\x9f\xe3\x9a\x66\xcb\x38\xb4\x89\x1b\xa4\x92\x63\xaa\x44\xaa\xd9\xa5\x9c\xae\xd3\xc6\x75\x32\x6d\xce\x8d\x54\x2c\x90\xfb\x41\x83\x3b\x3a\xf0\xf1\xed\x5f\xca\xa7\x82\x81\x96\xfd\xd6\x64\x31\xcb\x47\x05\xee\x6d\x98\xf7\x6d\xee\xa8\x6e\x1d\x33\x6a\x75\xcc\xf8\x57\x4f\x30\xaa\xe9\x4c\x8c\xd1\x1b\x5d\xf7\xb1\x74\xb0\x22\x8e\x0d\x05\xe7\xd5\xdd\x3d\x76\x54\x53\x62\x44\x0d\x6e\x07\x87\x9d\xcd\xb1\x7a\xc8\x9d\x2a\x56\xc2\x50\x0e\x8e\x19\x9a\x88\x6d\xc9\xe8\x03\x46\x3a\x20\xfc\xa4\x91\x2d\xf9\x42\xbd\xc7\x71\x62\x2f\x28\x93\x4c\x5f\xe5\xcf\xa2\xe5\x38\x2f\x60\x41\xdc\xdd\xaf\x6a\xf3\x68\xd9\xb5\x30\xed\x89\xe1\xb9\xca\x0f\xc7\xc2\x3b\x77\x71\xe4\x23\xe5\xd0\xaf\xd7\xd4\x5c\xf0\x97\x45\xc6\x9d\x72\xf5\x65\xc0\x50\xb9\x8d\x45\x37\x28\x5a\x8e\xdf\x6b\x89\xea\xd0\x14\x13\x7a\xca\xf0\x53\xf0\x34\xba\x0b\x23\xc5\xfc\x86\x9e\x6f\xd0\x7b\xed\xed\xb2\x65\x5b\xd4\x96\x7d\xb8\xab\x83\x7c\x20\xf6\x7c\xd2\x37\x0d\x92\x6d\xba\x5a\xc6\x74\x4c\xbe\x76\xac\x99\x7e\xfe\x22\x42\xef\x80\x7a\xf2\xc9\x96\xcb\x1b\x8f\xd2\x88\xbf\xeb\xa3\xa7\x10\xe6\xff\x33\x7b\x81\x97\x68\x3f\xba\x2f\x79\x36\x89\xe6\x76\xb7\x50\x78\x14\xa8\xa2\x7c\xa9\xe4\x50\x07\xa8\xea\x0f\xfd\xe7\x75\x22\xe4\x2b\xf5\xe1\xc1\x37\xc1\x07\xde\x0a\xd6\x6c\xb8\x48\x66\x72\x96\x0c\xaa\x10\xb7\x28\xe5\x2b\xe4\x2a\x9f\x23\x7f\xa1\xe6\xa5\x75\x5a\xa3\xf3\xde\xe5\x34\xad\xbf\x2a\xd9\x76\x5b\xac\xa4\x98\xc7\x80\x9d\x6e\x5b\x67\xcd\xce\x55\xa8\x14\x1c\x6d\xb9\x91\x2f\xa1\x23\x1b\x25\xcd\xab\xc2\x7c\x9b\xe1\x2d\x9a\x06\xa2\x67\x5f\xd4\x08\x2f\x9f\xa0\x3b\x73\x2d\x53\x81\xea\xbb\x1b\x9b\xcf\x1f\x07\x2f\x70\xd3\x4a\xeb\x52\x0c\x33\xe8\x22\x77\x9d\x59\xa9\x65\x29\x24\x27\x6d\x7f\x24\xa9\x82\x43\x49\x24\x93\x7d\xef\xd9\xa8\x1c\x79\x56\x5b\xe4\x1c\x35\x7b\xe0\x3a\xac\xd8\xe7\xc7\x23\x9f\xe9\x3b\x3f\xd7\x0f\x47\x8b\xca\x35\x26\xa5\xea\x95\x6d\x9a\x3e\x18\x14\xcf\x4d\x17\x37\x65\xa0\xb6\x35\xe8\x25\x81\xc3\x1c\x7b\xe5\xcf\x06\xd4\x5c\x49\x0b\xe5\xd9\xc3\xf1\x40\xe4\xf7\xe1\x52\xca\xcb\xc5\x94\x28\xd4\x75\xe8\x13\x7a\x9c\x97\x17\x74\x9e\x80\xdf\x30\x13\xa5\xc0\x2b\xd7\xe5\x10\x95\x51\x61\xdb\xbf\x4f\x93\x7a\x89\x1a\x45\xb6\x19\x3e\x09\xb8\xa2\xfb\x7b\x65\x2e\x56\x90\xd7\x6e\x5c\x2c\x4b\xf2\xc7\xe7\x2a\xe3\x75\xa8\x2a\xfa\xe6\xb5\x66\xb7\xe4\xd4\xf6\xaf\x5a\x43\x43\x1a\xd7\x25\x50\x7d\x44\x5c\xa0\x06\x08\xe8\x00\xc4\x4e\xe2\xf5\x7a\x30\xfe\x9c\xe1\x18\xa4\xd5\x9d\x33\x02\x0c\x83\xe1\x2b\x05\x61\x4e\x5b\x6a\x85\x2c\x88\x79\x32\xd1\x11\x73\x97\xfa\x45\x42\xe2\x6e\x24\x1d\x04\x5a\x65\xd3\xa6\xbf\xd1\xc6\x86\xb7\xc5\x73\xef\x76\xbe\x32\x50\xaa\x7e\xb9\x35\x83\x29\x88\x27\x98\x83\xb1\x9c\xd9\xf5\x5e\x3e\x1e\xb7\x5c\xb7\xcd\xbd\xd4\x40\xf8\x88\x44\xd6\xc6\x32\xe9\x7d\xcd\xee\x6a\x88\xe8\xd5\x70\x7c\x0f\x51\x5f\x20\x74\x67\xf4\xc3\x43\x60\xb8\x95\x3a\xb7\xda\x19\x88\x2d\x58\x95\xda\x2b\x09\x39\xcc\xb8\x27\xd7\x18\xcb\xd6\x9d\xd9\x6a\x58\x0b\x8b\xfe\x20\x84\x85\xea\x8d\x3a\x29\x99\xda\x0f\x32\x18\x9e\x82\x7c\xb9\x79\x39\xff\xc2\x1a\xcd\xda\x77\x9a\x28\xd4\xd1\xa1\x74\xf9\x01\xfb\xfe\x11\x15\x74\x3a\x23\x43\xe0\x2b\xa5\x66\xd2\x62\x05\x0f\x8a\xa9\xf0\x70\xde\x31\x61\x1e\x1e\xd6\xcb\x9e\xf7\x62\xf3\xe1\xa1\x23\x02\xb2\x5c\x40\xa6\x83\xe1\x76\xf8\x14\x36\x80\x96\x57\x33\x8b\x42\x50\x26\xb8\x0a\xa3\x28\xf6\x1e\x74\xf4\x91\xcd\x1c\x6b\x64\xdf\x27\x35\x3c\x31\xef\xbd\x10\x7a\x6c\x92\x34\xb2\x88\xa8\xd5\x05\x2b\x58\x02\x3d\xc6\x55\xd7\x52\x33\x27\xbb\x36\x23\x34\xd0\x38\xdf\x4f\xe1\x92\x9a\xfc\xd5\xba\x51\x68\x91\xe7\x2f\xc8\x2e\xdf\xd8\xe8\x03\x95\xac\x14\x86\x8a\x52\x83\x39\xdf\xba\x30\x74\x3c\xa1\x7d\x23\xdf\xc6\xd0\x58\x7e\x4c\x18\xd5\xdb\xfd\x78\x6b\x90\xbe\x53\x5f\x0f\x52\x65\xf5\xc4\xfa\xdb\x83\xdb\xb0\x14\x1e\xd2\x5e\x6f\xd7\x0a\xfd\xa6\xe4\xed\xa8\x56\x3e\xdd\xd6\x4a\xec\x53\xef\x18\x7a\x16\x90\xd0\x40\x41\x8d\xee\xc5\x33\x26\x33\x49\x0b\x75\xda\x24\x4f\xf3\x8a\x7e\x37\xce\x5e\x5c\xc0\xc6\x86\x37\x38\x64\x2d\x50\x2f\xed\x4a\x1a\xf4\x2a\x29\x85\x3a\x20\xc3\x3a\x56\x97\x5f\xd6\x51\xb9\x92\xe9\x17\x52\x6a\xd3\x60\x93\x43\xd2\xdf\x75\x8f\x18\xaa\x72\xf9\x73\xce\x25\xfc\x11\x5f\x9e\xa5\x34\xf7\x87\x08\xfa\x06\x9d\xdb\x51\xf2\x8a\x49\xdb\x3e\x60\x21\xc8\x50\xd7\x16\xd9\x79\xcc\x24\x91\xe1\xea\x53\x66\x4e\x3c\xd5\x5d\x58\xa1\x1e\x9c\x67\x9f\xe3\xf9\xd2\x75\xb4\xcb\x70\x6d\xdb\xca\x89\x4d\x7e\x1e\x5d\xe9\xd9\xef\x03\xcf\xc1\xa6\xe8\x3e\xc2\x3c\x76\x84\x2d\x1f\x3b\xc2\x2e\x9e\x7e\x84\x4d\x1f\x6d\xa7\xfa\xb2\x43\x92\x8d\x44\x13\x2f\xa4\xbb\x53\x34\xd5\x2f\xba\xa5\xe2\x12\x19\xaa\x73\xdc\x7e\x65\x00\x48\x12\xf4\x1e\x55\x2d\x1e\xd4\x7f\xfa\xc5\xdd\x59\xde\xc0\x86\x0e\xe3\xde\x55\x8a\xc3\x20\xfd\x2f\xe2\xdc\x81\x55\x2f\xd5\xe1\x75\xa0\x9f\x92\xae\x8e\x5b\x29\x1d\xc3\x2b\xb4\xd4\xc9\x82\x78\xd3\xec\x91\x39\xeb\x6d\xbb\x75\xb8\x36\xb5\x2a\xac\xec\x89\x71\x97\x6d\xbe\x96\xfa\x86\x88\xd2\x94\xc1\xcf\x7a\xff\xe1\xa1\xf6\xe8\x04\xe3\x0d\x33\x3b\xdb\x40\x08\xe4\xce\xe5\x8a\xaa\xef\x8b\xab\x49\x3e\x54\x27\x78\xe2\x68\x0a\x16\xd0\x25\xc9\x74\x5b\x3e\xde\x2f\x63\x7e\x62\x97\xba\x99\xef\x43\xf4\x7c\xdb\x2e\xd0\x39\x36\x79\xbe\xe2\x5c\xb5\xc3\xbd\x39\xfb\xac\x70\xf5\x82\xdc\x39\xe1\x59\x31\xa2\x79\x2c\x93\x8c\xa6\x7e\xb7\xcf\x4a\xc6\x5d\x97\xa5\x68\x04\xbd\x89\xc7\x36\x27\x64\xde\x2b\x4c\x0c\x3f\xf2\x19\xaa\xd5\x0c\x0f\x0a\x85\x5b\x3e\xcc\xd4\x4e\x52\xc0\x3a\x73\x83\x99\x82\x1b\x62\x6c\xf8\x3a\xbc\x12\xdd\x8c\xe4\x7d\x43\x78\x14\xb8\xef\x41\x8b\x9f\x0c\x1a\x01\xc1\x8a\xa5\x13\x74\x46\x05\x4b\xa6\x4d\xfb\x0a\x95\xf7\xca\xbe\xca\xda\x7f\xb2\x5e\x82\x03\xe0\xf2\xd6\x4e\xf0\x0c\xb8\x95\x7f\x02\x22\xe5\xa9\xca\x0b\xcd\x2b\x21\x88\x34\x88\x31\xdd\xf8\x29\x7f\x5c\xd7\xa1\x0b\x6a\x45\xdd\x06\xc5\xfd\x1f\xfb\xa2\x71\xeb\x13\xf7\x5f\xbf\xf5\xdf\x96\x3f\x62\xe9\xe4\xb9\x50\x7f\xfb\x0c\x10\xb5\xe6\x85\x54\xee\xbb\x90\x2a\x5b\x37\x4b\xf7\x72\xfd\xc6\xb9\x83\x87\xe4\x21\x51\x90\xa3\x8f\x60\x57\xc4\x5f\x02\x05\x26\x92\x5b\x24\x99\x97\x80\x1a\xc0\xc0\xa5\x63\xd9\x59\xae\x98\xa4\xbe\x5e\x6d\x76\xd0\xd3\x60\x6b\x74\x23\x79\x6d\xb7\xd0\x25\xdf\xfe\x21\xd4\x99\xdc\x05\x2d\x43\x19\x63\xf3\xfe\xd5\xdc\x95\x96\x4f\xb9\x2b\x9d\xa6\x33\x35\x54\xc8\xa3\x97\xe1\x7d\x1a\x07\x69\x20\xd2\xab\xab\x0a\x1e\xe0\x3f\x3c\x8f\x46\x0c\xfb\x21\x1f\x20\x04\x6a\x01\xaf\xf0\x1f\x9f\xe7\x39\xac\x1b\x7c\xa5\x07\x08\xa9\xf3\x11\xbe\xe3\x0f\xa2\xce\x23\xba\x77\x40\x3f\x81\xb8\x8a\x83\x2b\xf8\x9f\xd6\x90\x00\xff\xc3\xf3\x28\x87\xc7\x51\x8e\x4f\x25\x3e\x61\xaa\xfc\x1a\x9e\xf2\x6b\x78\x9a\x94\xc3\xaf\xbf\x2f\x4a\x44\xf6\x30\xcf\x10\x5e\x8e\xee\x20\x04\xfe\xc3\x33\x22\xce\x40\x3d\x25\xe0\x78\xc0\xbf\x01\xba\x97\xba\x4d\xa1\xda\xfc\x8b\xef\x33\x52\x24\x08\xe4\x03\x84\xe4\x84\x11\x93\x63\x8e\x43\x04\x13\x0a\xf0\x3f\x3e\x4f\xf0\x71\x42\x4f\xd7\x0c\x7b\xaf\x9e\x02\xf6\x1d\x12\xe0\x7f\x7e\x26\x9f\x18\x81\x7a\x82\x30\x84\x7d\x19\x05\x68\x77\x0c\x0f\x88\x87\x80\xfb\x62\x3e\xa9\xf1\x8d\x1e\x20\x64\x0c\xf5\x80\x7f\xf0\x94\xa7\x93\x12\xa1\x63\xe8\x17\xdf\x6f\xf1\xe5\x16\x9e\xf0\x73\xfc\x1a\x73\x87\x7c\xb3\x69\x1c\x64\x53\xfc\xbd\xca\x46\xf8\x08\x3f\x81\x20\x14\x6c\xf2\x52\xa0\x9e\x30\xec\x5a\x37\xd6\x3c\x53\x38\xec\x2f\x14\x46\x2e\x6c\xc6\xc0\xdc\x66\xe4\xb4\xa0\x24\x28\x1a\xf2\x5d\x82\x2e\x0c\xa0\x94\x9b\x7e\x1c\xdc\xf4\xe1\xf7\x15\xfc\xbe\x82\xdf\x1f\xe0\xf7\x07\xf8\xfd\x11\x7e\x7f\x84\xdf\x9f\xe0\xf7\x27\xf8\x7d\x0d\xbf\xaf\x03\x72\x4e\x02\x4f\xf0\x3f\x90\x8e\x4a\xf8\x0d\xf3\xbd\xc1\xe7\x8a\xbd\x24\xa0\x4b\x84\x29\xb4\x0a\x46\x1d\xc6\x3c\x27\x0f\x27\xf0\x48\xbf\xf0\x3e\x85\xae\x80\x7f\xf0\xe4\x60\xd2\xa0\x02\x30\x3c\x43\xcf\x7d\xbd\x82\x62\xe0\x1f\x3c\x65\x77\xd7\x19\x63\xd4\xc0\x6f\x20\x1d\x96\x04\xf4\x03\x6f\x19\xe2\xee\xc0\x6b\xc6\xf8\x3b\x13\x28\x70\x92\xe3\x6f\xf1\x15\x9f\x8a\xaf\x81\x98\xa6\x39\x82\xd4\xa4\x88\x5e\x80\x26\x6c\xf0\x38\xc3\xa7\xea\x2b\x3e\x56\x98\x82\x20\x82\x18\x1b\x08\xff\xa3\x4f\x09\x7e\xc7\x27\x0c\xc3\xb9\x80\xff\xe9\x99\xa0\x6a\x32\xea\xcb\x22\x85\x71\x84\x7f\xf0\x54\xd6\xc3\x2a\x9f\x41\x63\xd4\x53\x20\x58\x06\x1c\x2b\x59\xb0\xc0\x09\x87\xf3\xad\x9c\xcd\xe5\x7c\x53\x4f\x14\x46\x23\x59\xca\x51\x04\x06\x92\xba\x86\x7f\x03\x01\x89\x21\xd5\x2c\x85\x1e\x44\xf8\x1b\xf8\x81\xb7\x9c\xbc\x14\xc1\x7b\x2e\xdd\x15\xcd\xe8\x8d\x9f\xca\x6b\x5e\xd0\xea\x29\x10\xbf\xc7\xc1\xef\x81\xa8\xd0\xbd\x03\xe4\x85\x98\x34\x88\x45\x53\x2d\xae\x60\x95\xe1\xff\x40\x40\x72\x48\x57\xa7\x53\x48\x83\xff\x03\xa1\x5a\xa5\xda\x54\x4b\x45\x9d\x40\x3e\x04\xd2\x41\x89\x42\xd9\x81\xf7\x69\x4a\x80\x3c\xf8\x03\x6f\xe5\xa2\x1a\x22\x06\x0f\xfd\x06\xec\xa5\x24\xc0\xff\xf0\x3c\x07\xf6\x00\xa6\x02\xff\x06\xd2\xfb\x48\x40\x3f\x01\xfa\x07\x80\xe7\xc5\x15\x3e\x4d\xa7\x28\x0e\x0d\xe4\x03\x86\x60\x05\x09\x13\x88\x1c\x7c\x04\xf4\x03\x6f\x4c\x32\xe6\x4c\x33\xe6\x88\xd3\x83\x08\x3d\xb0\xf5\x30\x35\x53\x4f\x10\x86\xcb\x01\x02\xf0\x07\xde\x6e\xe0\xf1\x06\x7f\x69\x82\xcf\x79\x86\xcf\xd1\x63\x50\x80\xff\x03\xe9\xf4\x24\xa0\x1f\x78\x83\x29\x30\x47\x98\xa2\x2a\x45\x90\x28\xfa\x01\x76\x0c\x18\x30\xf8\x0f\x8d\x5f\x40\xcb\x03\xa0\xda\x41\x4c\xff\x05\xc2\xe6\x03\xdd\xa3\x9f\x40\x7c\x43\x62\xf6\x0d\xa9\xd9\x30\xaf\x88\xac\xf2\x2f\xfa\x1c\xc9\x67\xc7\x29\xd6\x46\x3d\x21\x5d\x19\x13\x51\x19\xc3\xc8\x64\x13\x08\x46\xb2\x2a\x1f\x02\x01\xdd\x77\x4d\xf3\x3d\xa3\xf9\x9e\xf1\x73\x5a\xfd\x19\x1d\x2e\x10\x9f\xe7\xbe\xe3\xcc\xaf\x69\xe6\xd7\x5f\x71\x3e\x61\x59\x33\x2a\x47\xb9\xca\x09\xe4\x03\x84\x94\x93\xbb\x6b\x1c\x6b\xf9\xc0\x21\x5c\x96\x7a\x62\xb7\x21\xe9\xc4\x94\xe7\xbe\x07\x82\x5d\x97\xb0\xcf\x92\x7a\x8e\x18\x55\xf8\x1f\x9e\x6f\x71\xe8\x6f\xaf\x79\x7c\x78\x6c\xe0\x99\x27\x08\xfd\x04\x4b\xb4\xf9\x6d\xe1\x64\xff\x01\xbe\xd0\xec\x80\x71\xff\xed\x6b\xdc\x9a\x9f\x01\xa4\xb0\xa3\x1c\xad\x28\x74\x35\x0f\xfe\xbc\xe6\xb9\x54\x1a\x47\x17\x4a\x1a\xfb\xa6\xde\x2d\xbc\x6e\xdb\xf7\xa0\x84\xca\x65\x02\xd4\x7e\x87\x72\xd4\x3a\xbc\x2f\x0b\x86\x27\x43\xf8\x94\xc2\xc6\x2b\xa3\x00\x83\xcd\x65\x5e\x09\x9d\xca\xbc\x7e\x99\xf1\x0b\x7d\x25\x71\x48\x5a\xb9\x39\xe1\x3a\xd3\x76\x28\xe6\xdd\x0e\xfd\x32\x33\x61\x4b\x32\xf6\xb4\x61\x4a\x43\xc7\x38\x24\x50\x8a\x8c\x1f\xe4\xb6\x3e\x4f\xaf\x39\xe2\xc3\x97\xb3\xb3\xa3\xcf\x81\xb2\x0f\x39\xaf\x04\x7a\xf0\x66\x1b\x9c\xd6\xd1\xd1\xba\x48\x64\x63\x37\xad\xce\x1b\xad\x9b\xe7\xb6\x59\x9b\xbc\xcc\xe0\x58\xe5\x02\x63\x63\x63\x48\xce\x32\x42\x32\x6a\x33\x09\xe0\xcd\x60\x23\xa8\x5b\x0d\xe5\x37\x81\x15\x01\x23\x97\x1b\x9d\xf0\xbc\x6d\xcc\xa3\xf8\x27\xc3\xf9\xfb\x67\x51\xfc\xb3\x39\x07\xb5\xb1\x2c\x9b\x2b\xc0\xd5\x8d\xc6\x39\xfe\x1c\x80\x03\x72\x5d\x2b\xef\x7c\xe6\xb6\x06\xeb\x29\xaa\xfc\xc3\xa9\xec\x97\xb3\xc3\x4f\x90\xe2\x5a\x7b\xb6\xd1\x8d\xf5\xe9\xe5\xac\xc8\x22\xb8\xbc\x24\xe6\x80\x8c\x11\x3b\x52\xa1\x81\x9c\x2e\x88\xf6\x83\x87\x07\x4f\x19\x14\x13\xb5\x5d\x2b\x1b\x20\x82\x71\x0f\xd1\x20\xf5\xb1\x13\x98\x80\xac\xfa\x58\x56\xa4\x50\x4b\xc2\x6e\x75\xe1\x92\xf7\x0a\xe0\x0a\xf1\xd0\x96\x24\xc9\xee\x76\xde\x23\x95\xca\x3d\xe9\x6a\x30\xce\x07\x57\x78\xe3\x88\x4a\xdc\x24\x17\xd0\xc0\x34\x24\x4d\x37\x32\x57\x2b\x46\x01\xfa\xd8\xc6\xba\xd1\xfd\x19\x8b\xb9\x8f\xe0\x64\x03\x53\x0b\x8d\x41\xd0\x63\x60\x88\x17\xf7\x47\x28\x74\x41\xc4\x22\xdb\xce\x96\x6c\x73\x94\x00\x12\x56\x85\x51\xc1\x53\x02\x42\x39\x0c\x8e\x72\x43\x95\xdd\xe6\xd0\xa9\xa7\xd8\x3f\x08\x75\xb8\x42\x99\x61\xc9\xc2\x79\xa2\x41\xbb\xa7\xa7\x6a\x55\x38\xea\xd3\x0b\x9f\xbb\xca\x61\x2b\xd0\xf9\x66\xd2\x26\x92\x0d\x27\x1d\x5e\x93\x4f\x95\xd4\x51\x2c\x1d\x7b\xd4\xb7\x6d\x3b\xcf\x43\xf4\x13\x27\x71\xa1\x1d\xfd\x4a\xa9\xcf\xf9\x88\x72\x65\x0d\xbc\x73\x66\x39\xf5\x84\x09\x22\xab\xd1\xa5\x6c\x19\x76\xc1\x65\xda\x76\x99\x3e\x8d\xcb\x49\x03\xb7\x08\x15\x30\x27\x3d\x85\x46\x27\xf6\xe1\xa5\x0b\x35\xe9\x7b\x72\xcf\x9a\x19\x48\x63\x8b\x05\x1c\x0c\x2a\x72\x9e\xf4\x2d\xb9\x0b\xef\x8d\xe3\x36\x20\xb5\xbb\x49\x5f\x9c\xf0\x90\x9f\x26\xf7\xc4\xf9\xc0\x27\x74\x1e\xc3\xdf\x8a\xdc\x35\x01\x33\x0a\x3f\x7c\xcc\x40\x4f\x4d\x15\x3b\x6e\xa2\xdc\x99\x2d\x87\x07\xc9\x7d\xc3\x13\x71\xd4\xf0\x4b\xbc\x30\xfc\x32\x27\x8a\x6e\x9c\x98\xc1\x83\x27\x66\x86\xe0\xe1\xdb\x15\xd7\xec\x30\x79\xf9\xdf\xe8\xf1\x72\xe7\xc5\xff\x7b\x21\x7f\xe3\xcb\xbf\xf5\xfe\xf6\xe2\x6f\x23\x74\x7f\x29\x8e\x10\x9b\xe3\x0c\xfe\x35\x28\xf2\x20\x75\xac\x03\xf5\xe6\x60\xc9\xb5\xd2\x1e\x91\xc8\xe7\x29\xaf\x3e\x51\x5f\xd3\x56\xc5\x14\xd5\x2a\x9d\x4b\x69\x05\x7e\x7a\xae\x97\xe7\xc5\x76\x00\x3c\xdf\xbb\x97\xc1\xa6\x0e\xda\x0c\xde\x07\xae\xf7\x5a\xde\x06\x61\xb5\x14\x67\xe9\x35\xcb\xd4\x77\x8a\x91\x45\x3a\xf0\xea\x79\xd3\x4e\x2b\x27\x26\xa7\x25\x68\x97\xcd\x1c\x55\x31\x1e\xcd\xa8\x53\xb5\xc5\xd7\x1e\x51\x24\xc1\x3b\xab\xe6\xae\x4e\x8a\x1f\x36\xa2\x8a\x0c\x5e\x44\xe5\xf8\xeb\x80\xc7\x7d\x4f\xea\x3c\x6c\xf6\xb2\xa8\xf0\x0e\x47\x5e\xd3\x54\x40\x7e\xbf\xc1\x3e\x83\x3e\xef\xcb\xa4\x8b\x9c\xd1\xed\x63\xa6\xe8\x3f\x30\x5b\xb5\xe4\x2d\xb8\x13\x60\x01\x53\xda\x1a\xb5\x4a\xa4\xef\xe1\x61\x33\x85\xa9\x14\x02\x58\x20\xbe\x43\xb1\x99\x04\x6b\xc1\x66\x0a\xdb\x37\x69\xa8\xf8\xe0\xc2\xf5\x85\x29\x0d\x2b\x5f\xe1\xb4\xb2\xc6\xed\xa5\xd1\x48\xa3\xa9\xb3\x89\x65\x2c\xf0\x73\x3d\x82\xce\xf0\x7a\xe5\xf8\x41\x30\x08\x03\x24\x13\xac\x99\x95\xe8\x31\x82\x7d\x11\xcf\x7b\x8d\x20\x7d\xce\xb1\xc3\xc9\x2d\x4a\x12\xfc\x0d\x48\x9f\xa3\x61\xec\x9d\x0a\xe8\xb8\xa3\x63\x73\x36\x83\x9c\x6b\xdc\x1d\x78\xee\xf1\xbe\x6e\x3a\x48\x85\x2c\xf5\xfd\x5b\x99\x7c\x3f\x97\x9b\x77\xa5\xf9\x87\x8b\x6d\xf3\x2c\x3d\x42\x26\x72\x0e\xb1\x17\x32\x13\x6d\x4f\x2f\x5d\xcc\x14\x7d\xc1\xe8\x08\x8d\x27\x44\x6d\x73\x60\xab\xd8\xc7\x87\x35\x10\x75\xef\xef\x65\x5e\x84\x41\x60\xfb\x88\xf9\x67\x94\x82\x06\xab\x2e\x84\xfd\x1a\x40\xa8\xff\xf3\x88\x5a\x48\x1e\xdd\xaf\xa4\x42\xce\xfd\xb1\xd9\x8e\x73\x98\xfe\x99\xd6\x0b\x6c\x26\xd2\x9d\xa2\x93\x90\x7b\x13\x5f\x2e\x5e\xa9\x2d\xae\xd9\x74\xc5\x04\x22\xda\x51\x68\x75\xaf\xf5\xd4\x07\xf6\xd1\x52\x02\x2b\x22\x4c\x8c\x4a\x5a\xdf\x9c\x71\x6c\x93\x00\xca\x9f\xe8\x52\x1d\xb5\x38\xfa\x2a\x22\xea\x51\x3e\x3c\x00\x99\x28\x51\x97\x30\x08\xd4\xf5\xa8\x9f\x37\x62\x84\x95\x16\xbd\x2a\xa2\xed\xcb\x36\xbd\x2a\xa2\x38\x5c\xf4\x72\xc8\x22\x2d\x46\x69\x35\xc2\x5d\x8a\xcc\x42\x31\xb0\xe1\x21\x1a\x9b\x84\xa0\x3c\xbc\xed\xab\x8c\xf9\x0a\xb5\x9d\xaf\xe9\x35\x39\x8f\x87\x49\x0a\x39\x03\x33\x45\x7d\xb2\xdd\xd1\x84\x78\x2e\x51\x5e\xbc\xbd\x3c\x5c\x4f\x92\x89\xe9\x57\x04\xb7\xd9\x1e\xae\x26\xad\xc3\x28\x5e\xc9\x49\x4e\x18\x55\x84\xfa\x7f\x12\xad\x4f\xda\x03\xf0\xf0\x30\x84\x92\x7d\xe1\xed\x81\xd1\x59\x0d\x23\xcf\x17\x1b\x1b\x13\x48\x08\x6d\x18\xc2\x4f\x73\x5c\x31\x4c\xc2\xe3\x94\xc9\x70\xd0\x39\x8a\x9e\x5d\xa7\x10\x43\xd4\x33\x79\xf6\x48\xf2\x0a\x79\x64\x24\xa1\x07\x97\xa5\x49\xcd\xbb\x91\x3f\x6d\xe9\x2c\xbb\x47\x50\x13\x57\x52\x6c\x4d\x5c\xe7\x16\x71\x9d\x37\x88\xeb\x93\x69\xf0\x8a\x23\x5c\x67\x94\xa4\xf8\xa2\xee\xde\x3d\x10\xd9\xf0\x91\xaf\x17\x92\xfe\xe7\x4c\xff\x4d\x0b\x10\x47\xca\xbf\x33\xe0\x0a\xe1\x6f\xf8\xfa\x16\x36\x02\x38\x5f\xc8\xc4\x2a\xa8\x1e\xf0\xef\x42\xf9\x61\x1d\x6e\xdb\x94\x59\x51\x44\xb6\x2c\x27\xc0\xe4\x8d\x8d\xf5\x99\xa3\xce\x68\x9d\x12\x70\xdf\x10\xaa\x3a\x88\x9c\x55\xae\x48\xb9\x59\xb2\xa9\x3c\x54\x62\x3b\x5d\x27\xf3\x16\x35\x37\x74\xf3\xfd\xd3\xa3\x56\x1f\x0e\x5d\xbd\x4a\x55\xdb\xa1\x84\x8d\x5d\x65\x6a\xc0\xdf\xb9\x20\x8e\xa1\x39\x8c\xd8\x00\xa9\x6d\xc6\x45\xcc\x3a\x6d\x2a\x3d\x89\xfd\x67\xcc\xa5\x18\x35\x2f\xbe\x53\xe1\xe3\xeb\xff\xf9\x2b\x6f\x38\xff\xdc\xb2\xd5\x8b\x84\x55\x90\x47\x05\x71\xc3\xbf\xa8\xd2\xa1\xed\x4d\x13\x69\x6f\x6a\xdb\xcf\x3a\x2c\x73\xda\xfb\x00\x87\x1a\xe0\x03\xed\x14\xc9\x09\x81\x9d\xb7\x04\x93\xfe\xe3\x73\xcc\x90\xae\x1e\xd7\xc7\xfe\xa3\x73\xfc\xfa\x11\x5f\x27\x2b\xdc\x2e\x3e\x7a\x96\x8e\x7f\x7e\xeb\xb1\x0d\x16\x9e\x83\x34\x84\xff\xe4\xbf\x05\x5f\x75\x5e\x8e\xfb\x6f\x3a\x8c\xba\xbd\x90\xb6\x8f\x5a\xf0\xbf\x7d\x0c\xff\xaf\xe9\xef\xcb\xe3\x04\xf2\x93\xf6\x6a\x79\x56\xa5\x33\x9f\x80\xb6\x4b\x88\xfb\x98\xff\x2f\xdb\x66\xb5\x6e\x4a\x6c\xe9\x86\x2d\x62\x1d\xc3\x47\xe5\x9e\x1f\xe9\x3a\x4e\x4b\x3d\x3f\x1e\x9d\x1c\x1a\x99\x67\xe9\x97\x79\x1a\x19\xa4\x11\x73\x2e\x3d\x48\x43\x4d\x42\xd0\x42\xb4\x6e\xf8\xc4\xc4\xb7\x13\xf4\xd2\x8c\xae\xb0\xf0\xaa\x51\xae\xea\xa7\x7c\x77\x4a\x4e\x9d\x45\xc0\xce\x9d\x83\x86\x20\x74\xb8\x0a\x70\xd9\x37\x4c\xf1\x9b\x9f\xff\x65\x32\x52\x9c\x4d\x8f\xe1\x41\x58\xb3\xa9\x4b\x16\x96\x6b\xb1\x97\xa2\xa4\x4e\x74\xb9\x5a\x2a\x96\x7a\x24\x59\x75\x5b\x60\xb5\x68\x0b\x9d\xa4\xb8\xad\xb6\xf6\x4b\x76\xc1\xdd\xb1\x99\xc6\xc1\x6f\x1d\x31\xbf\xad\x4d\x81\xb3\x41\xb7\x9e\xe8\x23\x19\x61\xdd\xaf\xd7\x7e\xf3\xed\x45\xd1\x6f\x3d\x7d\x29\xf7\x1b\xfd\xae\xf8\xd4\x62\x71\xf0\x3b\x72\xea\xdd\x66\x95\x3a\xd8\x1a\x82\x67\x25\x37\xb9\xf3\x68\xb0\x08\xdb\x0c\x25\x9e\xf2\x79\x1b\x2c\xb6\x4b\xb4\x1f\x25\xe4\x72\xf7\x14\x4f\x5b\xb6\x02\xfd\xf6\xc5\x93\xf2\x5a\x93\x0d\xff\x67\x6a\xb4\xaa\x30\xeb\x64\x67\xba\xc6\x7b\xb6\x77\x8a\xaa\xec\xc6\x49\x21\x46\x41\x55\xf7\x8c\xd0\xe3\xd9\x0d\x9d\x8f\x2d\x9a\xfd\xb4\xcf\x73\x0f\x33\xc3\x19\x3e\x05\xe3\xe2\x29\xf9\x3f\x96\x4f\xbb\x38\x3f\x20\x47\xa7\x23\x0f\x04\x0d\x9b\xdb\xa0\x61\x78\x56\xea\xcd\x52\x64\xa0\xb1\x28\xbb\x42\x26\x06\x05\x36\xb9\xc2\x77\x90\x45\x48\x8c\xac\x41\xdd\x64\x65\x66\x86\x95\x71\x80\x38\x84\x6f\x01\x04\xed\xb0\xc0\x37\x2d\x83\x76\x58\xd0\x9e\x4f\x41\x33\x24\xf0\xce\x93\xc0\x13\x18\x74\x4c\x8a\xc0\x1b\x1c\x3c\x6d\xc4\x83\xa7\xa4\x0a\x9e\x30\x9c\xc1\xa3\x49\x90\xd3\x6b\x39\x20\x7f\x8c\x05\xf3\xd0\xec\xf8\xf5\xab\x47\x99\xb1\x2e\x7e\xc9\xe1\x8b\x3c\xaa\x79\x36\xb1\x06\x8e\xe6\x15\xee\x41\xff\x02\xb7\xd6\xff\x43\x1c\x8d\xd4\xdf\x79\x2a\x4f\x73\x20\xd5\x7d\x34\x57\x73\xf0\xf1\x64\xe7\x70\xff\x7f\x94\xaf\xf9\x54\xa6\x23\x11\x4c\xe0\xff\xbf\x1b\x6f\xd2\xdf\x7a\x06\x3a\xcf\xbf\xdb\xc4\x98\x5e\x3f\x7d\x56\xa0\xde\x97\x99\x12\x87\x7f\xfe\xb7\x99\x0f\x4f\xe7\x72\xc9\xaa\x54\x04\x19\xab\x6b\xfc\xbb\xcd\xa3\x67\x60\x0a\xc9\x9e\xd2\xd8\x8c\xa1\x32\xde\xb4\xf0\xc0\x42\x47\xff\xb4\xa5\x0c\xf3\x34\x86\xf7\x53\x5e\x7c\xcd\x46\xc4\xd7\x28\x3c\xde\xfa\x09\xb3\x72\xe1\x99\x95\x5d\xfe\x94\xdb\x8c\xb5\x7d\xc1\x6c\x90\x76\xc6\xfe\xcb\xe0\x9b\x36\xcb\x3d\x6a\x3a\x10\x0e\xa5\xa6\x22\xde\x28\xdf\x2f\xc5\x34\x59\x3c\x65\xc2\x4b\xd7\x72\x7a\xca\x7f\x3e\xfe\x72\x66\x26\x7d\xae\x05\x14\xf5\x45\x0b\xa6\xd6\x6f\x1c\x21\xf5\x54\x18\xc8\x90\xfa\x54\xde\x69\xdc\x4b\x5f\xc2\x84\xee\x94\x8d\xe2\x76\x6a\x19\xf3\xf0\xb0\xde\x57\x8e\x87\x29\x03\x29\x63\x9a\x6f\x4b\x65\xe6\x65\xa7\x8e\xcd\x98\x0c\xc6\xcd\x4a\x1c\xcc\x1b\x79\x4b\x5d\x03\xa7\x7e\x06\x5d\x52\xf2\x5b\xd2\xf1\x10\xda\x64\x43\x06\xb7\x3a\xcd\x7a\x92\x6d\x67\x5c\x6f\xb2\x94\xeb\xd9\x95\x1c\x58\x1c\xa4\x2c\xac\x81\x1a\xda\x1b\x5a\x75\xc0\xb3\x42\xe1\xc9\x4b\x7e\x0a\x55\x54\x2e\x02\xa5\x58\x95\xdd\xdc\x71\x90\x18\x75\xa9\xf6\xac\xa6\x3c\xdc\x49\x84\xa9\xa3\xa4\x79\xc6\x8f\x69\x88\xb7\x91\xa8\xe5\x81\xe1\x4b\x3f\xca\xae\x7f\xc8\xed\x3c\x44\x66\xf2\x8f\x94\x51\xcd\xed\x79\x76\xb1\xf4\x01\xfb\xae\x90\x23\xdb\x99\x0e\x2c\xfb\x72\xd5\x62\xea\x26\x34\x00\xf6\x9f\xb7\x02\x99\x22\x10\xed\xaf\x70\x82\xa9\xeb\xf1\xd6\x80\x4b\x49\xed\x8a\x9c\x69\x42\x04\x22\x08\x36\xe9\x52\xca\x1e\x98\xf6\x8d\xb6\x90\x53\xe2\x48\x8e\xa6\x2a\x05\x01\x40\x13\xe9\x4a\x04\x83\x08\x1d\x63\x06\x2b\x3e\x9d\x85\x95\x85\x3e\x94\xdb\xad\x46\x0b\x20\x42\xc1\x40\xfd\xc5\x52\xdf\x9f\x72\x24\xca\x13\x59\x76\x4c\x77\x9f\xc6\x1a\xb6\x3d\x46\x75\x52\xc2\x41\xc1\x1c\x33\x06\x51\x9d\x38\xef\xea\x63\xdc\x4e\x7f\x5f\x64\xd5\x1d\xbb\xad\x2c\xab\x1d\xa8\x2e\xd3\x99\xf3\x82\xd4\x1f\x36\xff\xef\xd3\xa3\xcf\x3d\xd6\xfd\xc8\xc7\x77\x21\xf5\xca\xe6\x9f\x2e\x48\x8c\x9f\xc8\x8a\x5e\xfc\x29\x22\xa7\x83\x63\xa0\x49\xf2\xb0\x33\xb6\x9d\x0e\x8e\xb4\x2b\xa2\x11\x8b\xaa\x47\x48\xe3\xa7\xd0\xbe\x92\x1e\x38\xd5\x54\xcf\xac\x11\x3a\x8f\x99\x72\x07\x5d\x27\xb7\xe7\xd3\x0b\x78\xbf\xb6\xfa\xef\x1a\xf1\x4a\xb5\x8d\x9e\xcf\xaf\x96\x5f\xdf\x6d\x25\x9f\xdd\xda\x26\xe2\x37\x6f\x9e\x24\x0c\xfd\xa7\x34\xe7\xba\xb8\xfb\xa6\x3d\x4e\x0b\xbe\xaf\xbf\xf5\x0c\x4b\x9a\x95\x1b\x5d\xee\xd9\xe8\x4a\xef\x46\x97\xb6\x74\x8a\xca\xe6\x26\x25\x75\xc8\x23\x9c\x85\xf9\x13\x76\xa8\x23\xa9\x73\xae\xb7\xa8\xa3\xe3\xb3\x03\x47\xe9\xf2\xc2\x87\x70\x6e\xc3\x1a\x77\xb3\x6d\xa9\xc5\xb6\x3d\x41\x57\xd2\x76\x08\xf5\xaf\x18\xdb\x86\x3c\xb9\xbf\xf5\x98\x69\x8f\xc3\x1d\x35\xad\xeb\x25\xc2\xc5\xbd\x27\x50\x21\x84\x21\x54\x8f\x97\xde\xcd\x25\x6b\xe5\x30\x5b\xa5\x46\x4c\x6d\x29\x31\xda\x3e\x8d\x50\xe7\xd4\x76\x53\x46\xea\x29\x53\x14\xd6\xcf\x26\x8c\x93\xde\x40\x41\xa3\x2f\xf4\x27\xd9\x37\x06\x42\x09\x83\xb3\x9b\x0c\x01\x1e\xb3\xcd\xe0\xb7\x35\x1c\x87\xb5\x7a\x31\x9b\x4d\xf2\x6c\xb4\x36\x2f\xd7\xde\xb1\x0a\xff\x7b\x2d\xe4\x4b\x61\xf8\x30\xbb\xb5\x7c\xbc\xf6\x9b\x2a\xee\xb7\xb5\xbc\x5e\x9b\x57\x8b\xac\x17\xc8\x9b\x57\x28\xfe\xff\x48\xe9\x6b\x35\xd0\x6e\xc4\xf9\xc2\xbe\x6c\xd7\x61\x9c\x42\xe1\x58\x89\xa6\x3b\x14\xa5\xa1\x90\xe3\x12\x72\xc8\x72\x8f\x97\x46\xcd\x1d\xc8\x13\xd1\x74\x23\x5d\xbe\x23\x63\x87\x58\x80\x79\xa2\xa1\xe6\xf3\xf7\x15\xc1\x78\x14\xe7\x40\x7a\x51\xcd\x09\xd5\x34\xf9\xd6\x9a\x12\x96\xcd\x84\xd2\xd8\xbc\xe5\xf3\x06\xaf\xac\x99\xd9\x41\x57\x56\xf0\xcc\x4d\xce\x90\x24\xa3\x02\x92\x13\x86\x60\x12\xac\x3a\xc3\xf5\xc2\xb2\x45\x47\x81\xd0\x1c\x93\x77\x62\x39\x2f\x41\x3c\xbd\x46\xb6\xeb\x5b\x50\xb8\xcc\x80\xca\xdc\x72\x23\xd9\x1f\x47\xda\xc1\xee\xd7\x9d\xfc\xfc\xe2\x09\x64\x6e\xe8\x21\x73\x13\x2f\x99\x7b\x26\xef\x3e\x69\xd2\x40\x69\x8d\x62\x33\xf1\xab\x48\xe0\xa9\x34\x5e\xd1\x24\xf0\x74\xff\xd3\xfe\xae\xc5\xa6\xa7\xa2\x96\x6c\xfa\xe2\xc2\x42\xdf\xbf\xb7\xb9\xdc\x38\x17\xb7\xfc\xfb\x0c\xf6\x59\xb3\xae\xab\x98\x51\x9b\x45\x16\x37\x8f\x73\xa6\x5e\x22\xed\x27\x5a\x4f\xe2\x67\xbb\x48\xda\xb6\xa6\x5f\x71\x8b\x7f\xb4\x7b\xc6\x10\x3a\x7f\x7c\xf4\x08\xeb\xaa\x74\x17\x3b\xea\x91\x6d\xfb\xc8\x34\xa1\x16\x2b\xf8\xb3\x28\x5e\x37\x14\x73\x3d\xb1\xcd\x01\x54\xa8\xd1\x7f\xf7\x57\x72\xfb\x91\x36\xc4\xed\x78\x95\xf5\xf6\xf9\x45\x1c\x04\xd1\x93\x78\xd9\xda\xc3\xcb\x2a\x52\xea\x65\x69\xbd\x4d\xdf\x6a\x70\xba\xa2\xc1\xa3\x8d\x56\xf1\x68\xff\x83\x6c\x98\xcd\x73\xd1\x7e\xfd\x1c\x1b\xda\x86\x77\xbe\x79\x42\xf8\x48\x48\x10\x2b\x67\x7b\x55\xd3\x69\x24\xd5\xfb\x7b\xda\x43\x3c\x21\xbd\x31\xb9\x38\xa1\xfe\x67\xa4\x04\xd4\xa7\x94\x24\x13\xc8\x6f\xd1\x1b\x2d\x60\xdb\x1a\x92\x70\x64\x90\xf7\x10\x0a\xf0\xac\x94\xcd\x39\x93\x48\x53\x39\xbb\x32\x1f\x1d\x97\x39\x6a\x80\xc0\x13\x29\x92\x56\xe4\x05\x79\xa0\x8c\x0e\xec\x8c\xd3\xa4\xdc\x54\xb8\x05\xf7\xe4\x28\x3e\x2e\x05\x9a\x37\xa6\xcb\x86\x11\x01\xd7\xfe\x5b\x5e\x8c\xca\x6f\x38\x5b\xb4\xc7\xfb\x8d\x0d\x4f\x20\xc3\xd2\xad\x67\x0f\x0f\x08\xac\x9a\xa1\x23\xf9\xeb\x6c\x97\x40\x25\x9b\xae\x4f\xb1\xf5\x69\x31\xbc\x29\x2b\xdc\x2f\x69\x0f\xe4\xd7\xa3\xf1\x18\x2f\x84\xcb\x04\xa1\xe2\x61\xba\x50\x74\xaa\xde\x64\xac\xf4\xb0\x40\x1d\xb7\x33\x0f\xb7\x70\x4f\xa8\x42\x27\xc7\x46\x7e\x76\x6e\x4e\x5e\xb8\x55\x2c\xb6\xb7\x62\x14\xb7\x9d\xd2\xc9\x07\x36\x6f\xd9\x4f\x13\x05\x86\x28\x47\x68\x30\x91\xe3\x87\xd9\xc8\x2b\x8b\x1a\x87\x60\x22\x87\x20\x24\x01\x40\x65\x2c\x40\x84\x0c\x90\x65\x31\xb2\x2b\x54\x75\xd2\x4c\x37\xb1\xd3\xc1\x1b\x8c\x86\x1d\x09\xaf\xaa\xba\xe3\x64\x06\xd5\x9d\x78\xaa\x7b\x93\x8c\x37\x87\xb0\x0d\xe9\xc9\xe6\x4c\xaf\xc1\x48\xfa\x02\xa8\xe6\xec\x67\x6f\xa4\x2a\x5d\x22\xc0\x15\xc3\x9c\x8e\x7a\xc3\x72\x32\x49\x67\x75\x36\x72\xe7\xc7\xed\xf6\x4d\x3c\xa6\x39\x72\xbb\x3d\x8e\x6f\xda\x2e\xda\x34\x2b\xe4\x99\xeb\x6e\x45\x9c\x39\x1d\x2c\x60\xf7\x1a\x43\x2b\x47\x36\x82\x21\x94\xb3\x1d\xe2\x14\xa1\xc2\x71\x61\x44\xb1\x7c\x79\x6f\xc5\xc2\x03\x39\x58\xa3\x88\x28\x76\xbe\xa0\x58\x5c\x1c\x1d\x6b\x06\x83\xb9\x33\x82\xe1\x4d\x5a\x01\x41\x20\x33\xdb\x95\xcb\x29\x57\x1f\x62\xaf\xd9\x9f\x55\x2f\xe4\x87\xd8\xe0\x30\x6a\x79\x8d\x83\x55\xe1\x59\x2e\xea\xa2\xd2\xbb\x92\x10\xa5\xeb\x7c\x12\x46\x17\x86\x1a\x1c\xa6\xf3\x9b\xde\x34\x47\x4d\x5a\xd9\x4a\x3c\xba\x75\xf7\x60\x1e\x5b\x5f\x50\x5f\xf1\xfa\x2c\x80\x36\xc3\xd4\x1d\x6d\x6c\xe4\xef\x35\x88\x55\x39\x00\x2a\x81\xfe\x4b\xa5\x99\x0e\xfa\x56\xcb\x71\x5d\x0d\xd9\xef\x22\x7c\x58\x6f\x6c\x2c\x38\xf9\xac\x6b\x8e\xcd\xcc\x1c\xab\xc9\xce\x09\x16\x40\x29\x27\x6e\x21\xb1\x4c\x77\x26\x13\x4a\x5e\x43\x23\xa1\x02\x30\x94\xe8\x13\x94\x73\x98\x61\x32\xae\x5d\xb8\xe0\x0c\x16\x2a\x03\x18\xe0\x99\x9a\xb2\xcd\x38\xe1\xe4\x81\x02\x03\x09\x15\x47\x77\x18\xdf\xb3\xe1\x02\x7b\xd5\xb5\xf5\x91\x2c\xa2\xbc\x93\xfd\x58\x56\xbb\x6a\x40\x79\xa9\x19\x8e\x11\x92\x58\x97\x94\x3b\x43\xbc\x23\x2c\xd9\xb0\x68\x01\x5b\x64\xf1\xa5\x46\x85\xca\x8d\x8d\x40\xcf\x78\xb4\x39\x53\x5d\xb4\xb1\xb1\x1e\x06\xf6\xe0\x62\x24\x8f\x39\xae\xe6\x7b\xdc\x84\xa9\xc0\x3a\x9e\xc1\x98\x95\xe8\x6e\xc8\x04\xa4\x71\x6d\x03\x3e\x8c\xa5\xd0\xdf\xd7\xa4\xf8\x0d\x49\x14\xba\x1b\x14\xf7\x7f\x7e\x25\xba\xdb\x03\xd1\x3f\xd2\x4e\xf8\x0c\x93\xd5\x2e\x69\xbc\x17\xc4\xdf\x6b\x72\x65\x0b\x1f\x1c\x15\x3d\x2d\xd2\x6f\x32\xe1\xf5\x53\xac\xa9\x16\x8e\x77\x91\xe5\x20\x85\x39\x63\x54\xf5\xfe\x08\x14\x3d\xcb\xc5\xb0\x3c\x3c\x21\xad\x06\xa8\x67\x2d\x46\x58\x98\xdf\x93\xad\x3f\x60\x0c\x24\xa5\x85\x4a\x47\xd2\x94\x6c\xb9\xfe\xf1\xd9\x8c\xc0\xf4\x09\xde\xa1\x41\xf3\x5a\xb0\x59\xf9\x6c\x45\x22\xb4\x06\xd9\xcc\x37\x83\x77\x2f\x31\x19\x5a\x86\xac\xb4\x42\x60\xc1\x84\x06\xe7\x6c\xa0\xb3\x77\xf4\xd7\x40\x59\x92\x6c\xce\x07\x85\xfe\xd6\x34\x02\x78\xcb\x56\x8f\x16\xa2\xf4\x29\x40\xb6\xb5\x42\xba\x14\xda\x11\x6f\x6c\x95\x66\x6a\xfe\x0c\xdd\xd2\xa5\x73\xe1\xbf\xe0\x25\xf7\x07\x75\x28\x9f\xaa\x23\xe9\x4c\xfd\xf8\xed\xeb\xa7\xe8\x3f\xd2\x62\x7d\x86\xed\xed\xff\x3f\x2f\xe1\xcc\xa1\x7d\xe6\xa7\x17\xe3\xf6\x85\xdb\x4d\x4b\xb6\xd9\xba\x80\xd3\x96\x4d\xe4\x49\xe3\x29\xf7\x6f\x67\x06\xf3\x41\x1d\xee\xcf\xf6\xff\xeb\x6c\xe7\x64\x7f\xe7\x5f\x7c\x0b\xa7\x00\xca\xdc\x73\xb9\x3a\xa3\xc2\xfa\x32\x3e\xca\x85\x2b\x30\x43\xd0\xdc\x10\xad\xeb\x98\xab\x78\x97\xf4\xf1\x96\x27\x3b\xdf\x42\xff\xb7\x24\xf9\x61\xf5\xb7\x24\xa1\x65\x4a\x56\x13\xd6\x65\x98\x7d\x22\x76\x6f\x02\x59\x2e\x01\x19\x84\xd6\x8d\x58\xb4\xe2\x7a\x6f\xd6\x21\x9f\xd0\x55\xef\x34\xd9\xf6\x5d\xf9\xb9\x82\x8b\xd5\x32\x0e\x2d\xd6\x68\x5f\xfc\x3d\x26\x1e\x68\x29\xee\xd9\x1d\xa2\x4d\xc3\x8c\x77\xfa\xd6\xe5\x97\xff\x22\x2a\xb7\x2f\xa2\x2a\x82\x4e\xfc\x43\x37\x51\x2b\x4f\xef\x93\x3f\x7e\x4c\xff\x77\xbd\x4a\x59\x7d\x6f\xe2\x95\xca\x3f\xc3\xcd\xbb\x24\x97\x55\x26\x67\x48\xfe\x8f\xec\x0c\x8e\xb4\x75\x2a\x27\x72\x0b\x2d\xcb\x50\x22\x49\x26\xad\xe4\x8f\xb3\x33\x88\x16\xf6\x51\xe1\xd5\x22\x31\xbc\x37\xe5\xc6\xb5\x80\x83\x68\xed\x50\x08\xf4\xdd\xfe\x01\x21\xc9\xb5\x30\xa6\x46\x29\x1b\xcc\x60\xef\x97\x79\x6f\x3c\x59\xd4\x37\xf4\x45\x26\x67\x76\xcd\x20\xad\x78\xf5\x39\x49\xce\x87\x62\x71\x01\x7c\x92\xe5\xad\x0d\x36\x65\xa6\x55\xc8\xa4\x5a\x8d\xf9\xb5\x4a\x67\x33\xc7\xe8\x57\x8b\x42\x26\xcb\xa5\x3a\xe6\xa2\x3c\xbe\x42\x0e\xb7\x55\xcf\x78\xbd\x2f\xae\x9c\x8a\xac\x40\xa8\xf6\xb4\x73\xe0\x6d\xfb\x96\x28\xb7\xe7\xa1\xfa\x3a\x9e\xf5\x24\x96\x2f\x64\xa9\x2c\x6d\x28\x66\xe9\x61\xa8\xbb\x27\x6b\x73\x8e\xd9\x63\x1a\xf7\x7f\x7a\x23\x5a\x63\x17\xf7\x5f\xf3\x5c\x7b\x8e\x53\x40\xdd\x81\x23\x77\xa7\x51\x5b\xc9\x1c\x0e\xfc\x5f\xb0\xd3\x77\xd3\x9a\x84\x45\x5d\xd7\x60\xd8\xeb\x47\xaa\xc9\x8d\x7f\xb6\x5e\xd3\xd2\x41\xb3\x88\xee\x0f\x7a\xb6\x9d\x87\xb4\x5c\xe1\xa5\x87\xe1\x1a\x6c\xe2\x2c\x12\x32\xe9\xf1\x64\x71\x9d\x17\xbf\x2c\xae\x64\x62\x2b\x90\x9c\x0e\x85\x8b\xce\xa4\x0a\x39\xf1\x17\xa2\x72\xe1\x71\x67\x42\xf6\x4c\xb3\xf7\x94\x32\xeb\x0f\xb4\x1f\x87\xf7\xa7\xf9\x74\x36\xc9\xac\x98\xf8\x93\xd8\x47\x97\x19\x9f\xb2\xf4\xd6\x09\x1f\x0a\x26\x9f\x76\x58\x2a\x0e\xcb\xab\x7c\x92\x9d\xa6\x63\xa0\x25\x04\x4f\x63\x47\x8f\x05\x9f\xe3\xec\xb0\xcf\xe2\x43\x06\x13\x2d\x23\x05\x1c\x3b\xa2\x5c\x62\xc5\x1b\xb0\x8f\xb2\xe6\x7f\xc6\xde\xcc\x87\xae\x3f\x24\xbc\xf8\xee\xfa\x80\xf9\x40\x27\xf5\x61\x77\x6a\x24\xe4\x72\x99\x86\x15\x26\xa3\x2f\x7a\x96\x6f\xd0\xf0\xa6\xfb\x6b\xb7\x1c\x38\xaa\xdf\x4b\x38\xbc\x3b\x46\x75\xbb\x54\x50\x6b\xdf\x09\xc9\xe1\x4a\x02\x39\x7c\x53\xe8\x62\xbb\x0a\xac\xeb\xc4\x60\x62\x9d\x32\x60\xdb\x97\x90\x21\xdb\x22\xc6\x78\xc3\xd7\x8c\x94\xe2\x08\x51\x0b\x5e\x09\x52\x2b\xa2\x9e\xb3\xf6\x1d\x59\x31\x2b\x04\x78\xe2\x71\x7e\x8d\x22\x83\xa7\x25\xfc\x3b\x4d\x22\x5c\xa9\xcd\xd6\xba\x81\xa1\x01\x56\xc3\x2f\x14\xa5\x54\x0b\x42\x22\x6a\xda\x3b\xc1\xd7\x76\x3a\x45\x9c\x4e\x11\x5f\x23\xbb\xbe\x0b\xa7\x98\xe6\x04\xce\x18\x74\x2a\x54\xdd\xcc\xc2\x13\x82\xea\x54\x51\xe1\xc4\x88\x14\xb6\x95\x02\xa4\x9b\x24\xde\xf1\x06\xd3\x28\x37\x9b\x66\x9d\x73\x6e\x65\x4f\x35\xd3\xd8\x07\xae\x70\x9f\xb7\x35\xb9\x81\xf9\xe7\xb5\xd9\xcb\x5a\xcb\xc7\xec\x67\xb0\x72\xb2\x62\xee\xd6\xd0\x42\x78\x61\x06\xae\x49\x32\x0c\xc3\xef\x5d\xb0\x86\xf3\xef\x90\xe9\xc8\x13\x00\xb2\x89\xad\x09\x60\x4e\x02\xab\x16\x78\x03\xf0\xa5\xeb\xa8\x32\xf2\x1c\x55\x6e\x9f\x2c\xf3\x98\xda\x32\x0f\xee\x89\xe6\x84\x31\x80\x30\x3e\xc9\xc8\x9d\x1b\xf5\x41\x61\x76\x5d\xba\xe1\x1f\xd9\x32\xec\xaa\xe1\xb2\x94\x94\x68\xf7\x57\xfa\x31\xfd\xde\x88\x55\x0a\xd9\xdf\x1a\xe1\x52\x4b\x71\xd7\x0d\x96\x7a\x1e\x91\x38\x71\xc3\x4f\xd5\x5d\xe9\xa9\x1b\xae\x4f\x4e\x91\x38\x6c\xc7\xd8\x0d\x3f\xf2\x1e\x07\xcf\xec\x50\x7b\xb7\xc2\x15\x6c\xc5\x1d\x28\x73\x4c\x08\x3f\x76\xc2\xed\xed\x08\xdb\xbf\xe7\xd1\xf2\xfc\x6a\x85\xf9\xe8\x00\x24\xf9\xcc\x49\x5a\x5b\x04\x44\xed\xa8\xa8\xea\x36\xab\x5a\xcb\xe2\x93\x8c\x6d\x6e\x5d\x10\xf5\x77\x19\xf5\xd7\x3f\xfb\xa6\xf4\x17\x8e\x95\x87\x57\xd8\xe4\x8f\xd3\x6b\xdb\xeb\xa4\xc5\xea\x48\x13\xd4\x38\x5f\x32\xcf\xd3\xb1\xb8\xe3\x9f\x48\xf8\xd0\x5e\xda\xf1\x6b\xe2\x8a\xbc\x0b\x3b\x7e\x4d\xcc\x51\xd7\xb2\x8e\x5f\x53\x9e\xfe\x45\x1d\xbf\x26\x26\x6a\x95\x4c\xd3\xbf\xa0\xe3\x37\x94\xeb\xca\xe5\x1c\xbf\x79\xfb\x4f\x9d\x3b\x9e\x21\xbf\x91\xab\x30\x7e\xfb\xd3\x4a\xa9\x8e\xb3\x38\xe3\xb7\x6f\x44\xd7\x2a\xb4\xdd\xeb\x9a\x35\x18\xbf\x75\x0a\xc5\xc5\x1c\xf7\xb7\xb6\x9c\x30\x5a\x95\x10\xda\xb7\x43\xe5\xa2\x84\xe0\x57\x76\xb0\x5c\x93\x10\xfc\x83\xe8\x5c\x78\x10\xfb\x53\x33\x96\x16\x2c\x44\x58\x8d\xea\x20\x65\x90\xe8\x4d\x33\x91\x34\x68\xd9\x7a\xbb\xfa\x84\xe7\xae\x66\x88\x32\xa5\x99\xc5\x0c\xc1\x3f\x5b\xc1\xee\x5a\x8e\xfb\xaf\x4c\xe7\x78\x74\xef\xbc\x2b\x39\xee\xff\x40\x29\xbc\x8b\x0e\x4e\x02\xd4\x83\xed\x55\x0e\x31\x3f\x88\xae\x45\x0e\x91\x9c\x67\x6b\x8d\x43\x0c\xf5\x6e\xd7\x22\x86\x03\xc5\x4f\x74\xa0\x78\xcc\xa2\xc7\x7b\xa0\xa0\x4b\xa0\xf1\xa4\x2c\xab\x10\xe6\xc9\x7f\xce\xa3\x97\xf0\xe3\x51\x02\x23\xf4\x41\xd2\xa8\x7a\x78\xd8\x8a\x36\x0b\x9b\x0f\x70\x01\xd9\xd2\xf6\xf6\x85\xc3\xb9\x53\xa4\x93\xbb\x3a\x6f\x4a\xfb\x14\xf9\xb4\xa5\x7b\xd2\xfa\x54\xee\xf5\xf2\x9c\x86\xa3\xf6\xb9\xfc\xc6\xc6\xa6\x97\xe9\x64\x72\xc8\xd6\x6f\x38\x2b\xea\xf8\xfc\x42\xb0\x58\xfd\x74\x8e\xe8\x5f\xe7\x5b\x17\x08\x82\xff\x77\xd2\x26\xc2\xf3\x24\xdf\x53\x5a\xe7\xa1\x49\x4f\xc7\x13\xcc\x86\x9a\x2e\x8a\x07\xe6\xcc\x81\xdd\x92\x46\x76\x28\x21\x69\x96\x2a\xc5\x64\xc9\x96\x58\xf4\xb2\x02\xd1\x1a\x65\x2c\x3a\x5e\x66\x90\x51\xab\xc4\x56\x9a\x3e\x81\xfb\x7f\x4a\xeb\xb9\xd3\x14\xcf\xa9\xb9\x55\xf2\x52\xcc\xaa\x1c\x8e\x63\xdf\x87\x70\x6a\x07\x0e\xdd\xbd\xa7\x48\xe6\x0f\x0f\xed\x6f\x6c\xbd\x77\xfd\xe1\x29\x43\xd9\x92\x8d\x26\x50\x95\x72\x92\xf5\x08\xc3\x36\xcc\x7a\xd3\x74\x16\xb6\x7d\xaf\xdd\x07\x7a\xe6\xad\x0d\x91\x1e\xae\x15\x44\x77\x2c\x5f\x8e\x78\xce\x12\xc1\x59\x39\x4f\x27\x6b\x79\x21\x0b\x5a\x43\xfc\xda\xb5\x70\x5a\x47\x41\x0c\xf3\xaf\xa7\x23\x22\x11\xe8\xda\xac\xd1\x10\x36\x93\x66\xdf\x7d\x49\xa5\xc3\xe8\x46\x5a\x0e\x85\x84\x87\x26\x27\x98\x40\xda\x17\x9b\x2f\xdb\x97\x58\x77\x54\x43\x40\xfb\x49\x93\x69\xc7\x67\x5c\x82\xf9\x46\x51\x94\x3a\x96\x41\x70\x76\x8e\xe4\xf8\x1c\x14\x7f\x70\x7c\xf4\x87\x7f\x60\x7c\xc8\x79\xc1\xda\xfb\xb5\xa1\xa1\x10\xad\xc1\x39\xe8\x1a\x16\x7c\xed\x68\x93\x50\x15\x98\x94\xd7\xa1\x1c\x5e\x86\x26\x16\x54\x67\x0a\x39\x83\x00\xa8\x4c\x6f\x5e\x7e\xcc\xbf\x67\xa3\xf0\x55\xb4\x19\xac\x4d\x61\xd1\xd3\x5c\xb7\x9b\x2b\x5b\x76\x98\xce\x3c\x0a\x56\x1d\x9d\x20\x50\x69\x50\xdf\x71\xfd\x33\x1d\xf0\x2b\xac\x3a\xd4\xf7\x34\xad\xe7\xb6\x7b\x9b\x2e\x47\x93\xbf\x79\xca\x50\x0a\x77\xac\x48\x99\xdd\xdf\x76\x42\xdc\xfc\x27\x3b\x96\x2a\x07\x34\xf8\xb9\x93\x0c\xb7\xf7\xa7\x4f\x2f\xfe\xf0\x7e\xa9\xfb\xff\xbc\xec\x1d\xec\x5d\xee\x9c\x9d\x9d\x1c\x7c\xf8\x72\xb6\x7f\xf9\x79\xe7\x70\xff\x22\x81\x95\x3d\x12\x19\x99\x28\x24\xca\x5f\x4a\x2f\xad\xae\xeb\xa4\x61\x3e\x30\xa7\x50\x94\x34\xff\xf3\x3d\x70\x59\xc1\x36\x5d\x8d\x7e\xad\x72\x8f\x33\x2e\x25\x6e\x6f\x77\xc6\x79\x27\x49\x7f\xd1\xbf\xe8\x7d\xc3\xdc\xea\x41\x8e\x86\x32\xf8\xef\xe1\x01\x36\x19\x7c\xe8\xcd\x16\xf5\x4d\x78\x8f\x6d\x8b\x33\x46\xe7\x2e\x04\x36\x26\xae\x70\xae\xc8\x0d\xa3\x75\x2f\xa0\x6e\x30\x2c\x19\xad\xc2\x35\x4c\x20\xe7\x12\xb6\x91\x34\x81\x6c\x16\x76\x45\x06\xe9\xfb\x72\x50\x6e\x6e\x46\x15\x97\xaa\xe3\xd1\x07\x25\xe3\xfe\x89\x99\x18\x93\xa9\x88\xc4\x62\xfd\x9c\x7d\x43\xb6\xc2\x30\x08\xec\xc0\x27\xf0\x08\x78\x29\x2a\xea\xdc\x65\x64\x43\x35\xa1\x8c\xd1\x17\x46\x61\xbd\x48\x31\x23\x22\x75\xe1\x52\xa9\xf1\x89\xbb\x0d\x9f\xac\x6b\x30\x7a\x9f\xab\x51\x8c\x11\x88\x79\x9c\x0c\x43\x3c\x92\x17\xbd\x74\x36\x9b\xdc\xf1\x4d\x44\xe5\xdb\x66\x57\x0f\x93\xce\x15\xf3\x7b\x31\x16\x33\xee\x0b\xbe\xcd\x9d\x02\xa7\x74\x50\xcc\x4b\xbc\x5f\x51\xfd\xe0\xe5\xa6\xd1\xc0\x86\xae\xb3\xbb\xaa\xb5\x90\xd9\x77\xe6\xcc\xd3\xec\x86\xf5\x26\x0f\xf6\xc2\xea\xbc\x7f\x81\x3a\x61\xf6\xdc\x0c\x6f\x60\x2a\x2c\x04\x7a\xab\x63\x9d\xf5\x27\x98\x97\x63\xde\xe4\xdf\x0e\xef\x61\xf7\xd3\xe1\x8d\x7f\x55\x2a\x37\x99\xbd\x71\x55\x4e\x89\xa5\xc4\x6b\x1e\xf3\x66\xc7\x28\x0c\x0b\x5c\xa0\xa5\x49\x2b\x9f\x4d\xa8\x9d\xce\x5c\x33\x73\x5a\xf3\xee\xc6\x5a\xdf\x4c\x49\xb7\xc0\xe4\xcf\xef\x09\x76\xcc\xb9\x13\x7b\x41\xa3\x6e\xf7\xd3\x5c\xe3\x1f\x08\x49\x44\x16\x08\x7a\x10\xc5\x8d\x74\xd8\x2f\xd4\xa5\x7c\x8f\xa9\xaf\x26\x7a\x35\x9c\xf4\x32\xbe\xe2\xaa\x44\xdf\xf8\xd5\x9e\x21\xa4\x66\xa7\xab\x23\xac\x36\xcc\x90\x06\xd8\x13\x84\x66\x1b\x1b\x2d\x84\x27\x19\xdc\xed\xbf\x68\xdd\x5a\x5c\x8d\xe9\xf4\xc7\x1c\x1c\x37\x33\x61\x83\xaa\x66\x75\xf5\x84\x89\x5b\x8a\x10\xb7\xc9\x8a\xea\xe2\x77\x62\xea\xcd\x4e\x5c\x23\xf5\x34\xfc\xb5\xb8\x7b\x2e\x35\xc5\x06\xdf\x6e\xe7\xe1\x1d\x6f\xaa\xb5\x18\xc1\xa8\xc4\xd3\x8d\x8d\x6b\x26\x32\x5b\xdd\x04\x41\xad\xbc\xdb\x08\x3f\xe7\xea\xc3\xe7\x0b\x46\x6a\x45\xab\x0f\x69\x35\x76\x99\x40\x66\xe5\x2c\x8c\x06\xd7\xe7\xd7\xa6\xe8\xcd\x64\x21\xf0\x4b\x4d\xc6\xf0\xe3\x17\x97\x11\x05\x6a\x72\x46\x39\x4a\x3b\x92\x56\xb8\x9a\x3d\x77\x36\x20\x70\x7d\x3e\xba\x30\xbe\x77\xd4\x65\x2e\xfb\x65\x15\x04\xdb\x1d\x7b\x47\xf4\x92\xe2\xb6\x57\xc4\x99\x7c\xe2\xe0\x1d\x0e\x1f\x6a\xe2\xa0\xa7\xe0\x36\x98\xbb\x07\xce\xab\xf3\xe0\x05\x07\xe1\x95\x67\x5d\x07\x45\xa2\x71\xea\x8a\x5f\x6d\x91\x42\x49\xdf\x83\x0e\xe0\x9e\x2b\x35\xf2\x3d\xec\x67\x1e\xd8\x13\x65\xf8\x89\x48\x91\xd9\x66\x52\x19\xfa\x6d\xac\xf8\x5c\x1d\x69\x93\x21\xec\x92\x9d\x39\xa2\x4e\x19\xe6\xa9\x41\x1c\x73\xb9\x81\x47\xea\x01\xad\x4f\x7c\x24\x34\x93\xdb\x5c\x3e\x8a\x2b\x41\x9b\xfa\xe4\x9c\xd7\xdd\x05\xba\x65\x63\xf0\x36\xdc\xdd\x99\x63\x81\x2d\x3e\xf2\x54\xb5\x74\xaa\x2a\x94\xfd\xce\xa0\x32\x95\xd5\x26\x39\x39\xf9\x14\x87\x1d\x7f\x41\xde\xa5\xac\x99\x99\x5b\xe7\x22\x6d\x9a\x89\x9e\xa4\xd7\xca\x28\x4b\x72\x77\xfa\xa5\x17\xca\x01\x95\x28\xf0\x74\x5e\xd0\xe1\xfc\xde\xe1\x74\x81\x41\x31\x3b\xf6\x96\x30\x5b\xf9\x96\xda\xbc\xb7\x78\xef\x86\x3d\x59\xe4\x72\x75\x41\xce\x68\x84\x00\xd9\xc9\x80\xcd\xc4\x8a\x8a\xec\x1a\x5b\x49\x75\x18\xa6\xb6\x13\x44\x76\xb3\xac\x0f\x74\x18\x7e\x60\x27\xc0\x0f\x98\x4c\x58\xa9\x29\x00\x53\xea\x98\x48\x2a\xa3\x9e\xf3\xa8\x67\xec\xb1\xdc\xad\xcb\x7b\xc4\x2b\x94\x8c\x4c\x61\xbb\x4c\xa8\xd9\xa7\xb2\xab\xce\xa6\x8f\x16\xfa\xfb\x17\xd6\x39\x11\x98\x96\xba\xa5\xd9\xac\x11\x7e\x60\xb4\x71\x30\x61\xc8\x73\x33\xe4\xb9\x1a\x72\x42\xa9\x3d\xcf\x11\x42\x95\x06\x3d\xb5\x06\x3d\xb5\x07\x3d\x23\x68\xd1\x3a\x44\x87\xc6\x2a\xef\x19\xe3\x9b\x4a\xed\xf9\xf2\x7c\x76\xc1\x99\x8e\x93\xd4\x9d\x11\xb3\x8b\x41\x91\x8c\xd9\x67\x00\x30\xc7\xef\xd7\x82\xcd\xb1\x9e\x23\x15\x2c\x8f\xa4\x22\x58\xd1\xc6\x1c\x29\x98\x89\xb5\x66\x82\x55\x25\xc8\x14\xaa\x84\xdf\xd1\x01\x69\x33\x71\xe3\xd8\x27\x2c\x8d\x88\x49\x28\xc7\xca\x8a\x91\xe6\x5c\x37\x6a\xb0\x08\x5c\xb6\x8a\x74\xb6\x34\x4e\x37\x3c\x4e\x18\xa8\xc7\xe9\x66\xe5\x38\xe1\xa7\x2f\xf8\xe4\x06\xa3\x73\xe3\xa8\x56\x1b\xe6\x48\xb8\xfe\xb4\xe7\x8a\x32\xc0\x90\xd1\x60\x58\x63\x2c\xe6\xbe\x15\x98\x73\x6d\x2d\x4b\xeb\xf5\x3e\x0c\x28\x7a\x18\x2e\x6c\x0f\xc3\x30\x42\x68\xdb\x50\xe0\xd2\xcc\x91\xb3\x39\x42\xd7\x0e\xd1\x7d\x89\x86\x7a\x57\x55\x96\x7e\x5d\xae\x23\x3c\xa7\xea\x97\xfc\xe2\xfd\x16\xb2\x46\xf0\x40\x26\x6f\x9a\xac\x58\xfa\xc9\x4d\x85\x90\x61\xd2\xef\xbd\x22\x19\x58\x9b\x11\x45\xef\x47\x73\xa8\xab\xc2\xfa\x11\x07\x9f\x4f\xf7\x4f\xce\x2e\x0f\x77\x4e\xfe\xf2\xe5\xb8\x15\x7b\x78\xf4\xd7\xfd\xcb\xfd\xff\x3a\x38\x3d\x3b\xf8\xfc\x67\xc4\xb8\xbc\xcd\x02\x71\xb2\x4f\xc1\x9f\x8f\xf6\xf6\xd1\x5d\x0e\x07\xa2\xa6\xda\xe5\xee\xd1\xe7\xb3\xfd\xcf\x67\x9c\x8d\xc5\xf2\x29\x04\x27\x1f\xbe\xd4\x5a\xaa\x70\x6b\x57\xa1\x4b\xd9\xa9\xba\xb0\xa5\xd6\x08\xf9\xad\xee\x00\x96\x6a\xb4\xec\x69\x20\x51\xd2\xad\x2c\x83\xc4\x79\xa4\x62\x71\x29\x3c\x62\x88\x38\x15\xce\xe1\x39\xce\x85\x7d\x44\x85\x43\xe0\xa0\x85\x07\xd5\x52\x20\xa1\xbd\xf4\x31\x84\x94\xa6\xd5\xb6\xf2\x58\xd9\x50\xa0\xb6\x7d\x56\x6a\xe5\xa2\xe6\xb4\x69\xdb\x6b\xdf\xc3\x62\x40\x37\x09\x55\x36\x66\xd7\x38\x75\xd2\x3c\x3a\xb3\x1f\x6b\xc6\xa3\xa1\x03\x3d\xeb\x88\xc0\x87\xc0\x13\x4a\xf5\xa7\xb1\xf6\x4e\x4e\x64\x47\xfb\x91\x36\xbe\xca\x8d\x5e\x49\x52\x22\x6c\x99\xe6\xd2\x61\x0e\xe7\xb5\x2d\xdd\x27\x77\x0d\xea\x56\x5b\x69\x0c\xfb\xf4\xeb\x4a\x54\x80\x5a\x4a\x1c\x5e\x09\xba\x6b\x34\xec\x80\x42\x4c\x12\x34\x39\x5d\x93\x96\x46\xd9\x98\x81\x7a\xe9\x11\xbe\xb2\xe2\xa0\x2d\x1c\x87\xda\x8d\xf8\x46\x8b\xbe\x64\x4f\x03\x2d\x37\x03\x65\xb4\xb1\xd1\xc6\x10\xc7\xd0\x70\x01\x27\xf2\x24\xc3\x63\xf9\x92\x15\x9c\x9a\x47\xf9\x17\xaf\xb0\x86\xe8\xd3\x7c\x16\x2d\xb4\x5a\x66\x52\x68\x36\x76\xf6\xbe\x6f\x48\xcc\x38\x61\x95\xcc\x19\xde\x38\x6f\x0d\x66\xef\x6f\x06\x37\x40\x61\xc6\xe7\x37\x17\x26\xe7\xf3\x9b\xcd\x57\x17\x03\x2b\xb3\x31\x79\x0c\x20\x64\x64\xc9\x00\x92\x3a\x8f\x84\x5e\x70\x43\x4d\x43\x47\x91\xcf\x4c\x04\x1b\xa4\xda\x35\xa2\x76\x59\x3a\x44\x68\xba\x32\x14\x13\xdc\xa8\xd5\xf6\xa2\x9f\x80\x8f\x16\x0d\x6c\xa6\xa4\x7d\x66\x6d\x0c\x33\xeb\x9a\xb1\x1e\x92\x25\xe3\x93\xd3\x2e\xa3\x1c\xd1\xd8\x6a\x07\xdd\xe8\xd0\xb2\xa5\x46\x24\xee\xc6\xc0\xca\xa8\xb2\x82\xcc\xba\x11\xd1\x17\x73\x1a\x79\xc5\x60\x0b\xcb\xb9\xb2\x85\xc4\xaf\x0b\x59\x35\xf5\x2a\x98\x7a\x25\xef\x1a\x12\xf7\x7e\x98\x70\x19\x93\x84\x4b\x99\x25\xaa\x1c\x67\x4a\xf2\xa4\x5b\x97\x13\x12\x7a\x76\xc2\x4f\x90\x5e\xf7\x62\x24\xac\x54\x90\x27\xa4\x1a\x26\x6a\x66\x5a\x08\xe5\x9e\xa9\x59\x79\xa7\x66\xc5\x53\xb3\xba\x20\xbf\x18\x3c\x35\xc7\x2b\xa6\xe6\xd8\x3f\x35\xc7\xf6\xd4\xbc\x91\x53\x73\x8c\x8a\x0e\x5b\x83\xf1\xfb\xd1\x60\x04\x53\xf3\x06\xcf\x43\x66\x6a\x8e\x1a\x53\xf3\xa6\x31\x7d\x78\x74\x70\x0e\xcd\xec\xe1\xe0\xc9\xe3\xfa\x98\xf6\xcc\x9e\xf5\x70\x1d\x4e\xea\xeb\xf0\xa1\x4b\x41\x6c\x7f\xdd\x2d\x34\x87\x55\x7a\xf8\x4f\xf3\x05\xdc\x54\x18\xed\x3f\x06\xbc\xd1\x84\x71\xb8\xd3\x23\x2d\x15\x9d\x75\x80\x39\xf4\x11\x2a\x80\x3c\xf3\x07\x6b\x04\x13\xb4\x36\xbf\xd1\x37\x1e\x53\x82\x7b\x5c\x83\x15\xfa\x5b\xb0\x39\xdf\x0c\x10\xe5\x54\x26\x0e\xbc\xe6\xa5\x44\x0f\x3c\xde\xb0\xd9\x1c\xd3\x36\xd1\x5f\xdb\xd2\xe6\x97\x1e\x1f\xd6\xc5\x76\xe1\xfa\xac\x2e\xa4\xa3\x6a\xfe\x34\xe6\x1f\xfb\x48\x24\xbd\xa1\x5b\xad\xd4\x76\xe6\x1b\x1b\x58\x43\xf5\x6d\x8b\xad\x9e\xa3\xfd\x47\x59\x65\xa8\xb7\xcd\x82\x0a\x85\x9e\x4e\x6b\x0d\xdd\xa1\xb5\x52\xa0\x8e\xe7\x22\xfc\x13\x1e\xf0\xd6\x68\xda\x91\x03\x03\x85\x1d\x51\xc2\xc2\x99\xa3\xbc\x0f\x1e\xd8\x57\xf1\xda\x4d\x7a\x8b\xf0\x0e\x8b\x22\xff\x7d\x91\xad\xa1\x6f\xcf\x80\xf0\x20\x7a\x7f\x22\x0f\x1d\x4d\x4b\x3d\x1c\xdc\x5d\xe5\x27\x6b\x63\x63\x11\x06\x24\xab\x5b\x63\x87\x60\xb5\x93\x6b\x51\x16\x2f\x0a\x58\x09\x30\x0b\xd6\x90\xe9\x5c\xab\x4b\xa8\x01\x0c\x1f\x42\xd5\xe6\x35\x14\x93\xd5\x78\x0d\x3c\xea\x05\x0d\xf7\x5c\x0b\x57\x8f\x1c\x3a\x11\xf6\xee\x96\xac\x08\x15\xe8\xbd\xa3\x81\x98\xf7\x0f\x0f\x29\x10\xa9\xef\x24\xb3\x0e\xf1\x07\xf6\x4a\x1e\xed\x45\x93\x3e\xd4\xc0\x9d\x2e\xce\x6b\x42\x92\x60\x47\x0f\x41\x80\x29\xc9\x0d\x39\x13\x31\xf3\x04\x54\xa9\x31\x7f\x27\x49\x1e\xaa\xd8\x68\x00\x1f\xaf\x1d\xcc\xd7\xbe\xa5\xd0\x3e\x54\x0c\x1c\x41\xe7\xf2\x40\xa0\xe8\x11\x0e\x23\x93\xcd\x00\x26\xab\x65\x1e\x3a\xd4\x66\x44\x0d\xe4\x8e\x28\x5a\x01\x9d\x6a\xcb\x10\x6e\x9b\xfe\xe8\x91\xe2\xa5\x0c\xb3\xab\xa8\x57\x2b\x0d\x64\xef\x9d\x3e\x9a\xde\xcd\xd5\x41\xfd\xca\x38\x68\xc3\xff\x24\xd7\x84\x1c\xaa\x1c\x8e\x0f\xfa\x34\x00\x9d\x9d\x4b\x75\xfa\x68\xb0\x0e\xc7\xb7\x45\xaf\x40\x53\xd2\x28\xea\x8d\x60\x37\x19\x44\xad\x0a\x94\x12\x7e\x03\xab\x2a\x9f\xed\x0a\xb7\x7d\xcc\x29\x37\x1c\x53\xb4\x7f\x44\xb3\xbd\x83\xf1\xc7\x2a\xbd\x96\xad\xd1\x07\x95\x49\x87\xfb\x8a\x09\x94\x54\x87\x13\x31\x3c\x9f\x5c\x10\x7a\xac\x19\x82\x89\x71\xef\xa2\x1b\xd4\xed\x67\xa9\x94\x7e\x96\x52\xf2\x87\xbd\x1f\x06\x2a\x1f\xcb\xbc\x14\x79\x05\x34\xca\x86\xdf\xb0\x40\x9f\x4a\xa8\x55\x3d\xc4\x8b\x07\x98\x6e\xf7\x29\x50\x63\x74\x11\xa2\xef\x56\xe1\x13\xc2\x65\x41\x4b\xc8\xb4\x07\xc7\xd8\x1a\x4e\x34\x58\x83\x6f\x50\xd6\xb7\x73\x1d\x44\x73\x54\xba\xa0\xc1\x16\x98\x26\xcc\xec\xcd\x9f\x79\x06\x38\xda\x3d\xbe\x66\xc8\xb0\x5c\x8a\xe3\x32\x4b\xf6\xd6\x24\x94\x36\x31\xb4\xbf\x57\x9e\x2c\x80\x08\x3f\x04\x9b\x15\xfd\xcf\x69\x9d\x9d\xf8\xfa\xed\x04\x39\x29\xb9\xce\x52\x5c\x67\xd0\xe4\x10\x1e\xd6\xde\xd1\xc7\x6b\x2f\xdf\x4b\x73\x9a\x9a\x16\x21\x44\xc2\xc3\x1a\x82\xd5\x64\x3c\x6d\x68\x65\x31\xd7\x34\x5a\xbb\xba\x5b\x23\x5b\x3d\x44\x9e\x31\x5d\x31\x76\x0e\xc8\x64\x9b\xb7\x9d\x21\x37\x11\x23\xbb\x0b\x54\x97\xb8\xde\xed\xfe\x4b\x04\x25\xe8\xbf\xcc\x62\xfc\xb5\xc4\x58\x37\x21\x5f\x83\xa8\xe5\xa1\xf7\x10\xb5\x5c\xca\x2a\xbf\x46\xff\xe7\xc7\xd2\x53\x97\xed\x67\x87\x96\xa5\x94\xc2\x78\x19\x11\x2f\xd3\x02\xb3\x0c\xa5\x61\x05\xf2\x27\x40\xaf\xc8\x06\x25\x12\x18\x96\x50\x98\xdd\xbc\x91\xac\x9e\xda\x0a\x48\x3a\x2e\xab\x78\x49\x78\x7c\x8e\x6a\xf2\xc7\xb2\x32\x4b\x9e\x30\x15\x1c\x8a\x99\x31\xcc\x1a\xbb\x1e\x22\x20\x95\x8d\x8d\x09\x22\x3d\x9b\x00\xc5\xe5\x89\x6b\xfa\x8d\x84\x6f\xc2\xd3\x65\xaa\xc5\x59\xb3\xac\xe3\xd6\xab\x8c\x68\x2b\x77\xaa\x15\xdc\xd0\xe6\x3c\x96\x85\x23\x4a\xa7\xd2\xb8\xbc\xb3\x1d\xac\x37\x13\x90\xf0\x47\x79\xfd\xf3\x9c\x09\x5d\xcd\xcf\x86\x4e\xb7\xd1\x00\xc5\xb3\xae\xdc\x21\x3f\x16\x46\x07\xd4\xb6\x8c\xfb\xde\x3e\x45\x2e\x51\xed\x13\xd8\xe1\xdd\xe4\xe5\x7f\xff\x6d\xb4\xf9\x1f\x2f\xc5\x09\xbe\x9e\x26\xf7\x84\xc1\x07\xfc\xfa\xaf\x90\x18\x46\xe2\x70\x81\x06\x55\x23\xea\xa1\xf8\x46\x38\xdc\x7f\x87\x11\xd5\x6d\xe3\x8c\x60\x5d\x0c\x68\x46\x53\x5b\x56\x25\x49\xa5\x78\x99\xca\x48\x6e\x12\x60\x6d\xdf\xb5\x6e\x55\x51\x2e\x37\xb4\x2e\x53\xf3\x0b\xeb\xd4\x31\x42\x95\xf8\x6a\x29\x9c\x13\x8c\x47\x49\xe1\xf4\x99\x27\x18\xfb\x68\xd1\x6a\xb0\xb9\x0b\xbe\x75\xce\x20\xfe\x36\x8b\xa7\xb7\xab\xe2\x45\xd2\x68\x9c\x2d\xa3\x38\xb5\xb0\xce\x7c\x4c\x6f\xb7\xfe\x9d\x9e\xc0\x10\x6a\x74\xf8\x9a\x13\x2c\xee\xbf\x32\x91\xfe\xb9\x1b\xf7\x7f\xd8\xea\x4c\x42\xd1\x7d\xd1\x9a\xa1\x71\xff\xe7\x0e\x27\x1f\x2d\x36\xfd\x19\x68\x6b\x30\xbc\x13\xf6\x80\xda\x60\xa6\xa5\xa8\x0a\x23\x1b\x62\x7f\xee\xda\xf5\x75\x8a\x22\xea\xde\x89\x59\xdc\xd6\x2a\x3e\x4c\x67\x46\xd7\xcd\x5e\x6b\x13\x5c\x46\x33\xa5\x97\xeb\x5a\x21\xb8\xce\x61\x5a\x48\xc8\x64\x5a\x39\x36\xc7\x26\x34\x71\x1f\x5b\xb7\xa3\x2d\xa8\x25\x3b\x29\x73\xec\x0b\x24\x6a\x0a\x19\x75\x63\x03\x75\x83\x1c\x23\x68\xe1\xcd\xcf\x42\x10\x7d\x34\xcb\x7c\x65\x96\x7c\xd8\xb1\x33\x91\x13\x18\xa6\x37\x70\x17\x61\xb4\x1c\xa8\xfb\x76\x67\x15\xf2\xa9\xf4\x9e\x6c\xae\xd4\x5a\xbb\x11\x5a\xbd\x2f\x9e\x89\xbc\xfe\x0c\x6b\x54\x77\xe5\xc1\x5e\x5c\x2e\xdb\xa6\x8e\xdd\x93\xde\x1e\x38\x98\xda\x1d\x90\x8c\xfd\xc7\x00\x83\x78\xb1\xdf\x5f\x2f\xd2\x6a\xd4\xb0\xaa\x57\xbb\xb7\xb3\x4a\x81\x20\xdd\x53\xc6\x8f\xe1\x2f\xb8\x73\x39\x57\x2e\x81\x49\xa5\xb4\x66\x78\x13\xe9\x50\x80\x82\xa4\xe7\x60\xdb\x5c\xd1\xb5\xa5\x22\x99\xe2\x3d\x5b\x9c\x9e\x49\x08\xea\xa6\x92\x8d\x06\x0a\xc9\x15\x7f\xaa\x8a\x93\xd1\x83\x2a\x4c\x5d\xd3\xba\xd2\x02\xa8\x36\x65\xc5\x6c\xb7\xde\x7f\x9e\xcf\x68\xa6\xc7\x33\x8d\x46\x0b\x5b\x3d\xe9\x5c\x19\x1d\x5b\x32\xeb\xe7\x89\x16\x66\x28\xf8\x9f\x75\x7a\x64\x46\xb0\x16\xce\xeb\x63\x5e\xd5\x73\xa5\x2e\x02\x74\x53\xd1\xd0\xbc\xa1\x1f\xab\x44\xa4\x16\x3e\xb7\x12\x95\x16\x44\x0b\xa9\x91\x4a\x64\x4a\xda\x65\xb0\x4c\xf1\xe2\xaa\xeb\xfe\xd0\x57\x3e\xf0\x3e\x76\x76\x11\x30\x4b\x8c\x13\x82\x8c\xcd\xa0\x18\xc0\x91\x46\x67\x2d\x2f\xbc\xb0\x23\xaa\xb0\xb0\x2e\x32\x92\x2d\x02\x23\x34\x09\xe5\xc6\x51\xbe\xcf\xf9\xb2\x2a\xb3\x63\x61\xff\x90\xdc\xaa\xea\x5b\x74\x52\x0e\xcc\xe9\x54\x19\x4d\xab\x09\x81\xf2\x1c\xab\xf9\x30\x62\xa9\x70\xab\xeb\x82\x02\xa9\x31\xbb\x95\xd0\x37\x40\x11\x20\x6f\xdb\x09\x74\xd3\x52\xe3\x49\x70\x2d\xc7\x65\x39\xc9\x46\x3e\x48\xbf\xb6\x11\xc7\xcc\xa3\x85\x6c\x7b\x78\x36\xf6\xba\x37\x7e\x91\xfa\x48\xb3\x4d\x0c\xa5\x0e\xdb\x6e\x36\x37\x96\x3e\xf0\xf2\xa5\xb8\x2a\x51\xb2\x3a\x3a\x1d\x56\xe5\x64\x72\x8c\xea\x26\x64\x0a\x32\xb8\x09\x73\x1b\x70\x64\x94\xa9\xf3\x45\x1b\x3e\xde\x9e\x55\xc6\x4e\xd3\x9e\x58\x26\xb4\x39\xae\xc9\x16\xa2\x55\x0c\x11\xfe\x06\xbb\x06\xf1\x34\xca\x30\x87\x80\xf9\xb7\x72\x47\x72\x09\xd4\x67\x52\x9b\x64\x9a\xdc\x5f\xb2\x96\x32\x79\x63\x6e\x0c\x32\x9f\x77\x7e\x3d\xf8\xbc\x77\xf4\xeb\xe5\x2f\x3b\x9f\xf7\x3e\xed\xc7\x16\xc4\xcd\x36\x0f\x25\xa7\xaa\xb3\xf9\x2f\x5d\x24\x23\xba\x6f\xcd\x1f\xf4\x8a\x4c\xe8\x3d\x5c\x76\x23\xad\xac\x52\xb2\xbe\x0e\xc9\xf2\xba\x95\x4a\x93\x4c\x93\x76\x29\x9a\x08\xfa\x1d\x3c\x66\xa1\x56\x75\xb5\x5d\x4b\x0f\xd8\xe4\x37\x67\x4a\x67\x05\x3c\xb5\xd2\xd7\x0e\x77\xc7\x30\x83\x5c\xc4\x6e\x3a\x83\xcf\x9f\x51\xc6\x90\x3f\x78\x72\x21\xd3\xb2\xc8\x61\x48\x79\x0a\x31\x90\x82\x4f\x61\xd6\xe1\x3e\x75\x4b\x24\x85\x08\x6a\xfa\x3a\x60\x27\x36\x76\x91\x6d\x40\x17\xd3\x87\xea\x48\x9d\xd3\xa1\x98\x96\x16\xa5\xa2\xb3\xff\xb8\xe7\xda\x68\x87\x25\x89\xb1\xf0\x6c\x38\xb9\xbb\x47\x7d\x81\x49\x86\xc6\xc8\x05\x9d\xd5\xdb\xb0\xcc\x0d\xdb\x8d\xd7\x6f\x1f\xb3\xf2\xf1\x4a\x6f\xed\x05\x1f\xff\xdc\xde\xa4\x9f\x6a\xe7\xd1\xb4\xe3\x6e\x2c\xea\xb8\xcf\x86\x42\x2b\xd6\x34\x6c\xfc\x64\x86\xd1\x7f\x9a\xab\xb8\xd0\xc7\x1f\x36\xcf\x56\xcc\xd9\x38\xc3\xad\x79\x03\x21\x37\xda\xd5\xb1\x46\x4c\xe4\x4f\xe7\xa0\x3c\x54\x2b\x58\x9f\x16\x4b\xfd\x0c\x1f\x66\xae\x7d\x48\x37\x93\xe1\x31\x90\x74\xa9\xfc\xa3\xde\x41\x1c\x26\xd9\x0f\x06\xeb\xf8\x2b\x74\x11\x64\xda\x27\x63\x7b\x07\x69\x18\x59\xda\xdb\x87\x34\x58\xb1\x77\x0f\xdb\x7c\xef\xc6\xbb\xab\x00\x97\x6a\xf8\xf9\xd2\x58\xa0\x08\x6a\x59\x6c\xb9\x87\x14\x76\xd1\xf1\xc4\x8d\x50\x3d\x1b\x57\x56\x78\xe3\xb4\x50\xdb\x51\x4e\xbf\xc7\x79\x33\x4a\x76\x4d\x6c\xd9\xc4\x88\x46\xc7\xc4\x43\x2b\x0e\xdb\x1e\xcf\xac\x00\x63\x88\x3c\xb6\x42\x15\x92\xc3\x8d\x09\xf3\x70\xdd\x1e\x75\xb6\x36\x83\xf8\x74\x0f\x94\xdd\xf6\x7a\x0e\x7d\x79\xeb\xd8\xc7\xf9\x4d\xf2\x1a\x53\x0b\x96\xc5\x0f\x4f\x3c\xf0\xda\x5a\x75\x2d\xa3\xaf\x1f\xde\x78\x49\x10\xad\xb0\x3f\x64\xcf\x55\x86\x1a\x7c\x4f\x3d\xc8\xa5\x8c\xe8\xde\x4d\x4c\x12\x6d\xe1\xc7\x06\xaa\x72\x09\x0e\x99\x21\x26\x3c\x4c\xb3\xea\x34\x44\xa6\x59\x74\x40\x0e\x77\x86\xc4\x87\x58\x47\x5c\x38\x2a\xd4\x3a\x53\xd8\x1d\xd3\xab\x7c\x92\x37\x1c\x78\x1b\x0a\xb4\xb1\x11\x4a\x57\x24\x28\x9f\x24\xe0\x3e\x14\x09\x6c\x6c\x10\xc4\x12\x07\x22\x8f\x04\x6c\xa7\x86\x4b\x72\x52\xa2\x9b\xf9\x6a\xc1\xae\xe7\x7b\x43\xd6\x48\xd9\x1f\xe5\x64\xc6\xc0\x56\x27\xba\x32\x07\x05\xa9\x34\xd2\x39\xb0\x8d\x2d\x1c\x6a\xd0\x22\x6a\x69\x46\xc2\xfa\x78\x2e\x34\x6c\x1f\x01\x08\xc6\x74\x85\xe2\x6d\x1f\x34\x6b\x7b\xe1\x02\x35\x4a\x40\x62\x02\x3a\x22\xf9\xa9\x8e\xf2\xa1\x0a\x87\x11\x09\x54\xad\xe2\x91\x58\xf6\xdc\x0a\x0c\x50\x9c\x5b\xe0\x89\xbc\xa0\xbb\xdd\xee\xea\x60\xfc\x82\x20\x17\x75\x7d\x08\xda\x33\x45\x17\xd2\x6e\xcf\xb4\x6b\xc3\x1a\xca\x2a\x9e\x21\x2e\xc9\x8b\x7a\x96\x48\xd0\x4f\xab\x62\x14\x4d\xf8\x9f\x56\xe0\x7e\x31\x5a\xea\x0b\x95\x36\xec\x27\x8c\xb0\x67\xdc\x15\xcb\xf1\x18\x4c\xe8\xa0\x90\x1a\xe2\xea\xd8\x1f\xb1\x78\x3b\xd4\xd5\x7b\x51\x74\xa0\x78\xbe\x90\x60\x50\x92\x45\x8e\xa8\xde\x32\x75\x13\xba\xb3\x99\x76\x29\xef\x68\x32\xe6\x89\x24\x10\x63\x68\xc9\xfb\x1e\x1e\x64\xf9\x5b\x94\x2f\xf0\xdf\xa2\xf6\x77\xb4\x7d\x65\xe1\xe0\x92\x52\xd7\x7b\x14\x32\xf0\xba\x00\xc1\x4e\x85\x77\x5c\x9a\xc3\x81\x6a\x39\xce\x60\x18\x84\xd0\x4a\x34\x9a\xf5\x07\x87\x09\x4f\x92\x3c\x2a\x68\xf1\xab\x46\xa6\xd4\x28\xb1\xe1\xfa\x16\xba\x85\xe8\x04\x53\x2d\xbb\xe1\x52\x4b\x03\x97\xca\x75\xeb\xd5\x56\x77\xb3\x03\xc4\x16\x08\x5f\x9b\xa4\xc5\xfd\x2d\xda\x0e\x1c\x8a\x16\xf7\x79\x67\x31\x04\x0d\xd8\xbb\x1f\x84\x8f\x9e\x41\x04\x31\x75\xaf\x1e\x73\x8a\xe6\xa5\xc5\x37\x9b\x73\x03\xc4\xfb\xc3\xeb\xa8\x25\x36\xb0\xfc\x05\xa5\xd5\x0e\x9e\x80\xa1\x97\x6f\x1e\x1e\x32\xea\x6c\x1e\x1c\xaf\xac\x31\xa0\xe1\x40\xf5\x64\xf9\xe5\x16\x7d\x49\xaa\x85\x1c\x30\xd7\x0a\xf0\x11\xd0\x8b\x9b\xd6\x05\xbb\x2c\x9a\x95\xa0\x94\xae\x22\x5e\x6b\xe7\x21\xea\xcc\xa8\xf9\xee\x2a\x54\xaa\xfa\x6e\xc3\x04\x59\x5c\x41\xdb\xc3\x2d\x4c\x9b\xd6\xbc\x9f\x41\x0e\x37\x70\x6c\xb1\xd5\x10\x16\xfa\x58\x31\x0e\x4b\xca\xbf\x24\x97\xa5\xe3\x90\xeb\x81\xb8\x72\x96\x99\x84\x44\x87\x44\x78\x5b\x59\x85\xcd\x11\xeb\x8b\x26\xd5\xa0\x78\xa7\x26\xec\xc6\xc6\x3a\x56\xb3\x88\xe8\x3a\xd8\xc8\xda\x75\xa5\xec\x0b\xf5\xa1\xbd\xd4\xf4\x1a\xd0\x70\xd7\x66\x11\x28\xed\x4d\xa5\x7a\x11\x98\x4b\x2d\xb2\xcd\xda\x1a\x14\xef\x93\x54\x29\x7a\xe2\x10\xa6\xb2\xbf\xd2\x28\xaa\x20\x46\xdf\x1e\xab\x41\x48\x23\x52\xe4\xd1\x6f\x11\xe9\x80\xca\x3b\x3e\xab\x0f\x2b\x0b\xdf\xae\xc4\x3b\x79\x5b\xd1\x58\x5d\xd0\x2a\x6d\x3c\x32\x51\x09\x10\x97\x8f\x7e\x19\x81\x33\x8b\xe4\xf5\x7d\x8a\xc3\x17\x0d\xc6\xe1\xf0\xe1\x41\x76\xb1\xb9\x1d\x86\x66\xcc\x92\xe1\x76\x1d\x2f\x90\x27\x1d\x0c\x6e\x92\x19\x9a\x24\xc9\x3b\x5d\x22\x3c\xf9\xc6\xc6\x0d\xcf\xad\x92\x9f\xa0\x94\x70\x94\x14\x90\x6e\x08\xf5\x44\xb6\x35\x49\xd6\xfb\x0f\x0f\x14\x27\x1b\x34\x0e\x27\x9b\x9b\xef\x6e\xa5\x92\xef\xac\x83\x0d\xf6\x22\x2d\x06\xbd\x00\xb2\xbc\x51\xa3\x71\x9b\x20\x5a\xc1\x34\xb9\x6f\x42\xd8\xec\x79\x4e\xfb\x55\x38\xf3\x42\xdd\x84\xb8\xbd\x59\x11\x2d\x17\xb0\x6a\xb6\x6d\x66\xb4\x0d\x7a\xc5\x84\xce\x96\xa8\xb4\xea\x5a\xab\x8d\xab\x8d\xda\x51\xea\x9e\x54\xad\xa5\x1b\xd1\x37\x33\xf3\xfd\x8b\xbe\xbd\x66\xb2\x28\x9e\x6b\x75\x28\x25\x49\xb8\xcd\xaa\x1a\x88\xa1\xc2\xc0\x58\x81\x79\xc6\x33\x7a\x50\xae\xd3\x96\x87\xf3\xa3\xa4\x04\xeb\x7d\x41\x14\x97\x2d\x93\x26\x70\x22\xa7\x8b\x7d\x08\x84\xa8\xc8\x14\x72\xf6\xad\x3c\x06\xae\xa1\x6d\xa2\x88\x1b\xe8\x24\x84\x49\xc5\x45\xf2\x77\x02\x0b\x08\x02\x0e\xa1\x12\xac\xac\x76\x94\xc0\xa9\x95\x57\x2b\x9f\xa5\xb8\x54\x32\x4d\x60\x95\xa7\x65\xa1\xbe\x85\xbe\x1e\x52\xdc\x67\xd8\x45\xf6\xb2\x7a\x08\x7b\x60\x4a\x82\xf9\x85\xc8\x6b\x93\xea\x68\x1c\xa7\xe2\x74\xff\x78\xe7\x64\xe7\xec\xe8\x24\xbe\xf1\x08\x15\x3a\xf8\xeb\xb6\x78\xfe\xd5\xd3\x74\x6f\xef\x59\x01\xda\xb5\xac\x45\x13\x34\x12\x31\xc0\x50\x15\xe9\x44\x89\x1a\xa4\x56\x29\xcd\x28\x2f\xab\xdb\xf1\xdd\x52\xc0\x58\xf8\x3e\xd0\xaa\x80\xdd\x5f\xd6\x59\x53\x80\xd3\x59\xbb\xcc\x7b\x9b\xf0\xea\x69\x9e\xa3\x94\x99\xd3\xe4\x8e\x64\x27\xb0\x9f\xa9\x7c\x59\xda\xa7\xa3\xe5\xe5\x4f\x33\x81\xb7\xe8\xc7\x2e\xe5\x2c\x09\x42\x3a\x9a\x64\xd5\x0f\xaf\x48\x7a\x70\xbf\xfb\xcb\xfe\xee\x5f\x4e\xbf\x1c\x92\xed\x31\x99\x1d\xa3\x9b\xde\x79\xfa\x82\x1a\xfe\x82\xae\x9d\xeb\xc5\x34\x10\xe9\x68\xb4\x2b\x5f\xce\x4a\x56\xfc\xf6\xb0\xdd\x95\xc5\xbe\xa1\x02\x27\x29\x97\x86\xc1\xfb\x40\x04\xa8\x61\xd1\x6b\x17\xb7\xf9\xa7\x24\xf8\xd3\x66\xb6\xf9\xa7\xe0\xfd\x9f\x90\xd2\xa4\xc5\x49\x06\x15\x6f\x95\x60\x73\x78\xc8\x5a\x28\x25\xf7\xd0\x97\x29\xec\x65\xc8\xd6\x03\x57\x5b\xa3\x3e\x3f\xb0\xea\xfd\x2d\xe5\xa0\xc1\xae\x62\x89\x5b\x94\x33\x96\x39\xcf\x7d\xd5\x47\xc0\xde\xd0\x1d\xca\xab\xe7\xb9\xac\xb0\x9d\x55\xaf\xd8\x25\xc9\xa8\xa9\x30\xfe\x7e\x34\x4d\xac\x9c\xbd\xae\x8a\xcc\x5d\xbc\xee\x5b\x29\x93\x4e\xb4\x4b\xa3\xed\x17\xfd\xb8\xf0\xea\x2c\x9e\xd9\x3c\xf5\xc6\xc6\xef\xfa\xfa\xc1\xeb\x82\x22\x95\x5a\x5a\xa4\xb3\xf4\xc9\xe3\x22\x5d\x0e\xc3\xa7\xf3\xec\x82\x41\xa7\x81\xd0\x1d\x87\xeb\xa4\xec\x01\x7b\x1a\x86\x27\x73\xc9\x6a\xf2\x8b\xd1\x23\x75\xaf\x2d\xcc\xb9\x75\xee\x8c\x69\xf3\x3d\xdc\xa1\x9b\x92\x16\xd8\x3f\x57\x84\x2a\x5c\x30\x9d\x96\xf7\xca\x9f\xce\x8b\x0b\xe2\xd8\xed\x3c\xe0\x0b\x59\x39\x87\xa5\xd2\xd5\x68\xb5\x15\x39\xac\x49\xf8\xe9\x7c\x8e\x0a\x0d\xb0\x73\xe3\x53\xf2\xbb\xb9\xeb\xc2\xbd\x8d\x41\xb2\xa9\xd9\xf6\x55\xf6\xd0\xf4\xe7\x3e\xdf\xd4\x46\xf6\xfd\xac\xea\x90\xcb\x5e\xeb\x02\x15\x7a\x98\x75\xe8\x7d\x7d\xcf\xf5\xc9\x50\xed\x8c\xea\x93\xf9\xeb\xa3\x86\x21\x6a\x30\x3e\xbc\xf7\x46\xf7\xc7\xc8\x30\x46\x89\xe6\x74\x0a\x3b\x97\xc6\x0d\x5e\xc6\x3a\x21\x1b\x1b\x47\x30\xbe\x73\x35\x13\xd7\xb7\xe4\x96\xbb\xde\x77\x54\xc7\xf4\xcd\xbe\xdb\x1d\x63\xd3\x1d\x18\x61\x4d\xc6\x09\xb1\x58\xdb\xe4\xd3\xea\x1f\x50\x9f\xd8\xce\x90\x14\xa8\xfe\xc1\x57\x32\x57\xbd\xd6\x36\x09\x4d\x1a\x47\x12\x84\xe1\x1f\x2a\x4f\x99\x3c\x73\xf4\x9c\x9a\x9b\xfe\x6e\xcf\x35\xcc\xa5\x14\x95\x38\x44\xc7\xa5\x97\x79\xad\x2f\x52\x60\xb3\xfd\xbd\xe7\xb1\x0d\x42\xf9\x3c\x2a\xe2\xe9\x32\x6e\x9b\x00\x09\xa7\xbd\x4e\xc8\x23\xeb\x02\x80\x1c\xd2\x4b\xe8\xd4\x91\x04\x0e\x95\x7c\x46\x15\x89\x55\x79\xa8\x1b\x81\x9c\xe5\x50\x53\x9f\x70\xf8\xfa\x51\x81\xad\xa3\x09\xd5\xb0\x7d\xf1\xc8\xd4\x51\xf7\xa9\x2d\x6b\x97\xe6\xcf\x65\xe3\xa3\x86\xf8\xd8\xc5\xc6\x6b\xdf\x20\xee\x7b\x62\x59\x9d\xc3\x06\xc8\xe3\x6d\x41\x6d\x44\x0d\x94\x3c\x29\x39\xb6\x11\xf2\x74\xdf\x55\x0d\x88\x3c\x16\x10\xd2\x7d\x7d\x03\x24\xcf\x08\x95\x0f\x2d\xb8\x60\xbe\x30\x31\xb0\x78\x0d\xb1\xde\x99\x96\xe1\x69\xae\x49\xf6\xce\x41\xa1\x17\x94\x81\xc8\x63\x75\xcd\x79\xae\x98\x6a\x5b\x16\x7e\xdc\xe6\xec\x25\x44\x9e\xe3\x7a\x5e\x83\xe4\xb1\xa6\x34\xd7\xba\x95\xd9\xe7\x96\x8e\xd9\x55\x4f\x73\x7d\x88\x94\x37\x6d\xe3\x8e\x88\x4f\xa8\x2c\xf3\xf7\xa4\x2f\xbe\x24\x6f\xc5\x47\x7c\xf9\x80\xff\x7e\x41\x9b\x61\xb9\xbc\x7e\x47\x73\x23\x85\xee\xf2\xe1\xce\x3e\x5a\x7c\x14\x7c\x3f\x76\xc8\x57\x6d\x8d\x2d\x1c\xb5\x23\xc4\x25\x9b\x9d\x39\xc8\x1a\x1e\xa8\x11\xb9\xa2\x7f\xef\x39\x19\x02\x19\xb2\x4e\x2f\x27\x5a\x25\x43\x75\x37\xb3\x6a\x54\x9a\xa8\x36\x36\x74\x82\xdd\x74\x32\xb9\x4a\x87\x5f\xad\x14\x15\x62\x9f\xce\x09\xf2\xe4\x1a\x2f\xcf\x2a\x7f\x6d\x90\x60\x66\xa4\x71\x89\x22\x1b\xba\x3b\x4e\x92\xbf\x93\xca\xa3\x79\xff\x02\x33\xfc\x1a\xca\x42\x7b\x7d\xeb\x7a\x51\x56\x9a\xbc\x07\x69\x5a\x6b\x8a\x93\x33\x23\x34\x3a\x65\x1f\xd1\xb2\x74\x2e\x0a\xaa\x95\x0f\x82\xa4\xe3\x5a\xf4\x40\x02\x11\x23\x57\xf7\x7b\xaf\xdd\x22\xd2\xe2\x56\x85\x9c\x36\xef\x1b\x6f\xe9\x44\x8c\xd9\xa1\xb2\x5e\x13\xf1\x58\x16\x74\x8c\xb6\xfc\x2d\xe5\x6f\xc9\x5a\x7e\x3c\x87\xc3\x7b\x44\xd8\x04\x95\x22\xb3\x55\xd3\x26\x1f\x63\xbf\x02\xf1\xd4\xfb\x08\x0c\xae\x6f\x32\xa0\x54\x8d\xca\xf4\x9a\x5a\xfc\xde\x6b\xba\x9f\xd8\xa1\xbd\x4f\x29\x3d\xa4\xc0\xf1\x64\x28\x57\x4f\x91\xd9\x41\x9b\x16\x6c\x4e\x36\x92\xf3\x14\x75\x9e\x16\x49\xbd\xb1\xb1\x5e\x89\x21\xf7\x95\xaf\x9f\xa9\xd5\x0b\x7f\x0d\x0c\xfa\xbb\x84\x7e\x1f\x46\x62\xb8\x14\x5a\xb5\x99\x0c\xab\x30\xd3\xc7\x46\xed\xae\xa1\x70\x65\x9b\x50\xfd\x2e\xf5\xb6\xa0\x33\xd8\x11\x60\x67\xe6\x64\x81\xe9\x2f\x40\x0b\x21\xf1\x12\x96\x0b\x81\xd4\x23\xd4\x63\x91\xc5\x1c\xa3\x12\xe3\xef\xbd\x15\xd9\xf3\xee\x18\xe1\xbc\x68\xcc\x5b\xcf\x09\x20\x77\x99\xcd\x30\x4b\xae\x56\x69\x0f\x45\x02\x65\x22\x98\xa8\x25\xa4\x08\x21\xf2\x03\xf1\x6b\xa8\xf0\xe9\x1f\x72\xa7\x02\xc7\x21\x79\x52\x68\xac\xd2\x79\x63\x95\x0e\x4c\x3d\x45\x01\xd3\x36\xd3\xec\x48\xb1\x1d\xb6\xa7\x96\xaa\x2d\x71\x3f\xd2\xec\x76\x0d\xbf\x52\xcf\x58\x45\x3c\xc8\x23\xe7\xd2\xaa\xa5\xfa\xba\x41\x4f\xf0\x74\xb0\xdb\x2a\x0a\x6b\xe4\xd2\x14\xea\xbf\xac\x79\xf9\x84\xd7\xcc\x28\x27\x24\x8b\x99\x41\x84\xfa\x7d\x78\xb0\xa6\xd7\xd0\x8a\x42\x2d\x40\x3f\x57\xe7\x19\xb7\x15\xa3\x44\x1d\xf5\xc1\xee\x28\x2b\x63\xc5\x74\x7a\xb2\xec\x66\x2a\xe7\xd6\x24\xc7\x34\xba\x0b\xb0\x6c\xe2\x08\x51\x35\xa5\xb1\x6e\x9b\x42\xa4\xfe\xba\x92\xa2\x9f\x19\x5c\x17\xe9\xb1\x17\x0b\xd7\xee\xd4\xd5\x6c\xdc\xce\x1c\x99\xd3\xe7\x58\xa2\x06\x3a\xaa\x61\x4e\x29\x46\x87\x6c\x3e\x20\x2b\x1e\xe3\xec\x1b\xcf\x1b\xff\x5f\x77\x6f\xda\xdd\x36\x92\x25\x88\x9e\xf9\xda\xbf\x82\x42\x4f\x2b\xc1\x12\x44\x8b\xf2\x92\x99\xa0\x61\xb6\xcb\xcb\x54\x76\xa7\xd3\x3e\x5e\xba\xba\x46\xa5\x51\x43\x24\x28\xa2\x93\x04\x58\x00\x68\x5b\x2d\xf1\xbf\xcf\x5d\x62\x47\x80\x8b\x33\x6b\x66\xde\xab\x53\x69\x81\x81\x40\xac\x37\x6e\xdc\xfd\x8e\x68\x1c\x3e\x14\x93\x29\x04\x97\x8d\x70\x07\xf5\x77\xb6\xa8\xaa\x35\x79\x2f\xc7\xfb\x27\x91\x23\x76\x4e\x26\x63\x0d\x0b\x71\x2f\xce\x2e\x93\x1c\x56\xaf\x12\xbb\x1d\x49\xef\xf9\x64\x38\xaa\xb4\x2b\xbd\xe1\x89\x12\xa5\xe8\x04\x70\x72\x72\x39\x4a\x47\xdc\x74\xad\x96\x29\xed\x8f\xea\x31\xc2\x5c\x3d\x2e\x93\x34\xbe\x1e\xd8\xc2\xa2\x10\xf3\x6d\x62\xf4\x08\xd9\x07\x0e\xa8\x10\x61\xb4\x8c\x41\xa0\xa1\x8d\xa7\x14\x83\x71\x91\x1b\xcf\x87\xfc\x1a\x0d\xa7\xd0\x69\xa5\xd4\x91\x78\x54\xe8\xc7\x72\x63\xfc\x00\x9e\x92\x04\x5d\x1e\xd7\x7c\x17\xd7\x41\x73\x7b\x5e\xd1\x85\x24\xd0\x3f\x0a\xce\xe6\xeb\xc0\x16\x39\x50\x32\x36\x31\x34\x95\xd2\xd1\x62\x46\xbf\x7a\x05\x0e\xb9\x38\x85\xbb\xea\x49\xd3\xce\x12\xaa\x10\x25\x37\xca\x6d\x3e\xd5\xf7\x19\x1a\x7d\x8a\x0d\xab\x48\x54\x3e\x0a\x7a\xe1\x84\xa2\x03\xf7\x7b\xc1\x89\x94\x86\x22\x95\x51\x9f\x9e\x9f\x45\xf5\xc9\xf9\x59\xff\x24\xf8\x6b\xd1\x0b\xc9\x33\xae\xc2\x5a\xa9\xb7\xd6\xe6\x9d\xb1\x68\x47\xb8\x48\xed\x92\xe8\xa5\x38\x93\x36\x8a\x60\x67\x7d\xb4\xf9\x45\xd9\x19\xfc\xad\x23\x91\x11\x2d\x5e\xcb\xa7\xd7\x14\x27\x4b\x48\xaf\x26\xd1\x6a\x5d\xdd\xa0\x3c\x78\xb5\x19\x7d\x91\xd1\x40\xdf\x90\x0f\x66\x1d\xfe\x2d\x0a\x0c\x8b\xa2\xe8\xae\x8b\xfe\xe9\x8c\xcd\xe6\x05\x15\x6f\x8c\x31\x2b\xeb\xd4\xdf\xb6\x47\xff\xd9\x69\x18\x71\x90\x95\x7f\x8b\x67\x82\xb7\xe7\x7b\x19\x46\x6c\xb5\xc2\xf2\xd9\x51\xfb\x18\x26\x78\xf7\x70\x9b\x35\x85\x66\x97\xe2\xe1\xc3\xc7\x91\x8f\x5b\x8a\x87\x8f\xba\x53\x76\x78\x75\x83\x26\x03\x05\x65\xd2\xf8\x6b\x1b\xa7\x14\x0f\x39\x54\x74\x37\xa3\x04\x35\x7e\xf0\x3b\x2c\x58\x6c\x52\x7c\xce\x31\x98\xb7\x70\x49\x50\xe5\xb1\xcf\x2a\xeb\xfc\x10\xe3\x70\x7e\x3d\x15\xe1\x8f\x64\xc0\xb5\xb8\x89\x34\xe6\x67\xe9\x2e\x07\x45\x1a\x58\xc1\x44\x22\x23\x7e\x5b\xfc\x99\xdb\xc8\xfa\xa7\xc3\xc8\x08\x0c\xc2\x5f\xab\xb0\x73\xa2\xb1\x52\xfc\xd8\xb8\xfa\xd0\xc3\x46\x63\x05\x2f\xb1\x46\xc3\xb5\xba\x87\x91\xf9\xc7\x20\xb2\xb6\xef\x3f\x02\x23\x52\xca\xb7\xf6\x8f\x17\x6a\xbf\xa5\x9b\xdd\x7f\x08\x66\x5c\x96\xed\x63\xc8\x3a\xf7\xc1\x19\x43\x1d\xe2\x00\x54\x5e\xf6\x89\x74\x16\x70\xe2\x12\x86\xd3\xe8\x33\xf0\x24\x61\xdf\x72\x5d\xd6\x9f\xc2\x65\xf8\x59\x1b\x21\xb3\x6e\x72\xa7\x7d\x9f\x69\x6e\xf7\x06\x73\x56\x53\xa7\xdc\x23\xb9\xe3\x39\x76\x77\x96\xa8\xc4\xb4\xbe\xa3\xef\xac\xb7\x38\xa0\x29\x4a\x03\x3e\xe3\x3f\xcb\xe4\x8e\xc2\xbb\xc7\x77\x4c\xce\x8a\xb9\x75\x30\x24\x68\xc7\xa6\xce\xb4\xac\x2b\xaa\x8c\x44\x90\x3d\x41\x4c\xc9\xb7\x49\x25\xb2\x34\x72\x64\x4f\x3b\x96\x57\x85\x62\xea\xca\x15\x95\xa6\x7d\x49\xe0\x60\x94\x2d\x34\x5d\x74\xc2\xf7\x9d\xa4\xc0\xfb\xad\x5c\x31\x60\x8d\xa1\x11\x71\x20\x76\x62\xc9\x12\xdd\x3c\x10\x8a\x80\xcd\x2b\x4f\x4e\x24\x09\x97\x6f\xa2\x56\xd2\x44\x8b\x7c\x9c\x9f\x9c\x08\x6a\xf4\xe8\x8c\xec\x7c\x99\x9c\xf3\xcf\x72\x34\x53\x0c\x81\x5c\x15\xc3\xd9\x60\x9b\x2b\x28\xb7\x67\x7e\x2c\xf2\xf3\xa0\xcb\x27\xea\xc3\x39\x05\x9b\x95\x8a\x94\x78\x0d\x0c\x9b\x2d\x8d\x8c\xe7\xa7\xa7\xd1\x1c\x59\xb1\x31\x40\x5e\x5c\x87\x9c\xe6\x91\xc3\x34\x76\xed\xa8\x9c\x5f\x25\xe7\x27\x46\x62\x7d\x25\x2a\x03\x09\xeb\xe9\xad\x32\x7b\xbb\xda\xd1\x9d\xd0\x61\x79\x57\x0f\xa8\xe3\xd9\xc0\xe9\x58\x0a\x11\x28\x06\x84\x1f\xb2\xf2\x28\xbf\xbf\x97\xf2\x0a\x34\x4b\x88\x6a\x01\x60\xe4\xb7\x9d\x93\x71\x42\x97\xdf\xf6\x3a\xa9\x8e\x8f\xab\x8b\xf2\x12\x40\x29\x87\x3f\xa3\x35\x10\x99\x13\x91\xb7\x5e\x73\x64\xeb\xa8\x8e\xd0\xcd\x4a\x68\x82\xd2\xaf\xe1\xda\x84\x2e\x7c\x67\x15\x24\x75\x3f\x0e\xd7\xe4\xce\xdc\xfd\x45\xe7\x9e\xaf\x81\x56\xec\x9b\xb9\x51\x8d\x97\xcf\x85\x4a\x7f\x12\x01\xc5\x46\x4b\xd3\x07\x22\xf0\x64\xa3\xe6\x5b\xf5\x8f\x5a\x47\xa9\x04\x96\x23\x3f\x3e\xf6\xac\x02\xb0\x22\x5d\xa3\xa0\x55\x29\xcd\x4c\xa1\xad\x4d\xb5\x12\x2f\xee\x73\x1a\x1a\x39\xad\xd6\x2e\x4a\xdb\x7e\xb1\xe2\x6d\x55\xbc\xb9\x7a\x4f\x0b\x72\x97\x73\xc3\x79\x5a\x75\xc8\xb4\x5f\x24\x07\x6b\xb5\xd8\x17\x7e\xf3\xd6\xe7\x99\xdd\x00\x09\x4b\x7c\x03\xea\xdf\x95\x3b\xfa\xee\x93\x26\xba\x0b\xa5\xa4\x9e\xaf\x15\x93\xd4\xde\xea\x2d\x86\x0f\x2d\x8c\x88\xc9\xdf\x5b\x18\x11\xcd\x21\xf0\xa3\x91\x35\x46\x19\xa6\xca\x58\x22\x62\x4b\xf0\x0c\xb7\x80\xc1\x55\xaa\x73\xa8\x2b\x7d\x3e\x70\x5f\xed\xc6\xc9\xca\xb3\xcb\x22\xc1\xbd\x8e\xe2\x1f\x1e\xef\x6f\x92\xec\xbf\x08\x81\x06\x7e\xd2\x45\x03\x13\x25\xb8\xcb\x83\xce\xd0\xae\xff\x9a\xdd\xbe\xc9\x31\x04\x03\xe9\xd7\xab\xf0\xce\x0e\x1b\x47\xe4\x82\x1d\x2b\x8e\x8a\xcc\x48\x71\x54\x60\x45\x89\x63\xba\xa2\xad\xa6\xd6\x9d\xc5\xc3\x1f\x29\xa3\xf4\xf9\x01\x59\x17\x59\x8c\xe2\x71\xc2\xb7\x23\xe5\xf2\xaf\x91\xb4\xc9\x21\x27\xab\x22\x59\x99\xf2\x20\xf2\x18\xc7\x5c\x98\x2b\x8a\x9d\x99\x4c\x48\xb2\xe7\x6a\xa3\x45\xed\x75\xb8\x80\x77\xd9\x97\xde\x42\x87\x95\x12\x99\xf2\x7c\xe6\x79\x14\xe3\x08\x15\x88\x1d\xca\x63\x33\xf6\xc5\xcc\x74\x7a\x73\x5d\xcc\xd6\x6d\xc5\x8a\x15\xf3\x0c\xfd\x83\xd1\xd3\x97\x9e\xe7\xd2\x57\xd8\x9b\x3c\xce\x3a\x92\xe4\x6f\xd5\x95\x38\xce\x16\x27\xe9\x9a\x6e\xda\x37\xab\x5e\x1d\xae\x58\x04\xe6\xe6\x97\xb3\x6a\x01\x0d\x08\xf8\x75\x4a\xd1\xf6\xba\x42\x35\xc4\x95\x40\x63\x52\xeb\xa1\xd9\xe8\x5c\xbd\xe1\xe5\x83\x8f\x70\xf8\xc0\xcc\xe7\xb5\x35\x8f\x38\x35\x5c\x7e\xe7\x1e\x47\x03\xaf\x33\x91\xc7\x4c\xe8\x00\x2f\x17\x73\x93\x72\x4c\x6b\x49\x0c\x33\xf1\xd8\x1e\xeb\x1e\x0e\x60\xa5\x01\xf9\x48\x03\x72\xda\x34\xe9\x64\xfe\x3e\x9b\x75\xbc\x9f\x66\xe2\x3d\x2c\x37\x9a\xb8\x28\xf1\x72\x0d\x65\x1f\xcb\x76\xe0\x79\x20\x07\xcc\xd1\xa0\xf9\x77\x54\xe8\x6e\x84\xa0\x44\xe0\x37\xab\x35\x14\x85\xec\xdb\x9e\x2f\x70\x4a\x95\xcd\x6a\x3c\x5e\x28\xf5\xf4\xbc\x47\x5d\x84\x9a\x4d\xe8\x18\xf5\x0a\x7c\xe1\xd9\x94\x43\x1c\x23\xac\xd8\xfb\x85\x70\x80\xb8\xb3\x32\xb1\x70\x7e\x98\x12\x6e\x67\x59\x50\x45\xb6\x9c\xa7\xb5\x04\x3b\xa3\xfc\x17\x1b\x03\x00\xef\xac\x9c\x32\xb6\x4c\x78\x60\xf5\x8c\xc7\xc3\x5d\x03\x9c\xf2\xc3\x5d\xf6\xc7\xc2\x4c\xcb\x67\x67\xf5\xf0\x80\x30\x93\xad\x9b\x00\x91\x9c\x30\xf1\xe2\x10\x69\xe2\x07\x5e\x47\x2f\x8c\x92\xfd\x30\xfd\xc3\x03\xc2\xa5\x35\x46\x60\xe9\x4c\xe6\x6d\x45\x03\x58\x24\x6f\x13\x20\x81\x5f\x89\x54\xd4\x14\x24\x46\xb8\x9f\x5f\x21\x49\xab\x64\xe7\x88\x85\x29\xb4\x10\x46\x7c\xff\xdb\x3a\x87\x75\x46\x99\xe2\x49\x80\x91\xd3\xaa\x93\xe0\x3f\x28\xa0\x4e\x51\x36\xbd\x7a\x95\x4d\xf2\x59\x9e\x51\xc8\xb0\xe0\x24\x0c\xfe\x83\x62\xeb\xfc\xc7\x20\x90\x6e\x98\x12\x75\x87\x72\x1c\x1b\x69\xd9\xa5\x1d\x2f\x8f\xb4\xc5\x67\x41\x02\x76\xee\xd3\xae\x73\xd6\xbe\x64\xda\xf3\x94\x04\x4f\x86\x46\x41\x69\xf2\x19\x28\x57\xe4\x08\xd2\x23\x4a\x53\xc0\x17\xc6\x15\x46\xf7\x58\x27\x4b\x7c\x67\x5c\x3b\x62\xc2\x3f\x15\x14\xd8\x0a\x26\x53\xf3\x7c\x0b\x9c\x2f\xe2\x0f\x40\x23\xf8\x7b\x8d\xbf\x71\xaa\xf5\x7a\xb5\x5a\xe0\xd4\x9b\x52\xae\x4b\xd4\x83\xad\xa4\xdc\x48\x3a\xc6\x5c\xbf\x6f\xa9\x01\x94\x09\xae\x6d\x92\x65\xd8\xe6\x5e\x0f\x9a\x79\x0a\xa4\x09\xfe\xac\x69\xf2\x7d\xf7\x3e\xdc\x3e\x71\x8a\xa4\x64\xc7\x05\x53\xe1\xa7\x78\xf6\x35\xaf\xcc\xb6\xd9\xa7\x9e\xd9\x8b\x0d\xae\xb1\x6c\xfb\xec\x65\xf4\x38\x9a\xbe\xe4\x6b\xd7\xc0\x6e\xad\x9f\x96\x52\x5b\xb1\x96\x11\xc9\x50\xc0\x51\x62\x7a\x07\xa4\x3d\x61\xec\x93\x56\x88\x2b\x49\x9e\x4c\x76\x2f\x25\x8a\x61\xd4\x8f\x46\x1b\x18\xe0\x9a\xdc\xb4\x54\xda\x68\x38\x25\xb5\x04\x57\x70\x1e\xb6\x2e\x49\xce\x4b\x92\xb9\xd3\x17\xcb\x52\x38\x4b\xd0\x33\x85\xc0\xdd\x70\xd0\xf4\x1d\x13\x35\xdf\xe6\xe2\xe8\x43\xdc\x5b\x63\x65\x9a\xbe\xdc\x74\xda\xd3\x14\x15\x64\xe4\xd7\xf5\x6a\xeb\x2c\x4a\x63\x63\x3d\xb3\x70\x36\x52\x25\x72\xe2\xb0\x89\xe9\xde\x20\x3d\xe9\x9a\x8a\x8e\x05\x2d\x0e\x29\x46\x83\x56\x61\xea\x84\x93\x00\x1a\x6b\x36\x18\xaa\xdc\xe8\x67\x64\x1d\x5f\x37\x2b\xce\x41\x67\x99\x9c\x78\xb0\xa0\xdc\xef\x30\xc3\xc5\x8e\x9f\xd1\xe1\x37\xa7\x6f\x4f\x79\x71\x10\x4e\x92\xb1\xea\x00\x35\xa5\x26\x6a\x3a\x18\x27\x89\x8d\x4b\xf7\x3a\x95\xdc\xa9\x7d\x2c\x39\x4c\x3e\xae\xba\xcb\xf7\xaf\xfb\x7f\x87\x13\xba\xda\x0d\x19\x67\xa3\x52\x83\x44\x29\xf1\x04\x46\x82\x2f\x2f\x75\xd8\xaa\x54\x7d\x6a\x82\xc9\xe6\x1b\x96\xb2\xe3\x1c\x74\x6f\xf5\x6c\x0b\x96\x99\xfe\x9f\x40\x2b\xc8\xc7\xef\x87\x53\xe6\xff\x77\xa0\x52\x42\xe4\x1e\x37\x25\x77\xf9\x1f\x6d\xa0\x54\xd1\x1b\x9b\x8b\x35\xed\xfb\x44\x46\xcf\x9c\x58\xe0\xb8\x50\xa9\x98\x36\xbb\xc1\x8f\x42\xe1\xd5\x5f\x72\x0c\xab\xa8\xa3\x44\x4e\xd2\x3a\x0b\x8a\xf5\xf2\x1a\x45\x01\xf4\x43\x44\x41\xe4\x1f\xda\xab\x30\x96\x46\xb1\x23\x7a\x71\x8d\xc6\x9d\x69\xa1\x8a\x1b\x2e\x16\xab\x18\xfb\x02\x74\x2a\x56\x3b\xfb\x9c\x55\xb7\xe1\xd4\x08\xc4\x86\xee\x43\xed\x4b\x4a\x1b\xe2\x8e\x30\x22\xec\xd6\x40\x96\x19\xaf\x9b\x09\x87\xca\x58\x42\xb5\x22\xa2\x59\xcb\x31\x0f\x37\x96\x71\xab\x72\xc9\x11\x8b\x23\xb7\xde\x9d\xc8\x38\xa0\x2b\x3e\x88\x2d\xb6\xfc\x7d\x76\xf3\xea\xeb\x6a\xac\x56\xc0\x30\xce\x5d\x9a\xe1\x6b\x1a\x0b\xdc\x38\x11\x14\xca\x6e\xcd\xb6\x5e\x02\xcb\x2a\x9d\xca\x50\x82\x43\x11\x56\x3d\xbd\xc9\x3a\x55\x76\x03\x50\x15\xd8\xe9\x00\x4c\xcb\x58\xed\x6e\x6d\xa6\x7a\x36\xc2\x09\x9a\xf1\xfe\xba\xa2\x05\x5e\x1b\xa6\xa2\xaf\x25\x9b\x89\x46\xad\xc1\xd3\xa7\x69\x51\x16\xb7\xcb\x72\x5d\x3f\x7b\x16\x44\x5f\xc9\x33\xf9\x4b\x02\xc8\x22\x7a\x91\xdc\xd1\x6a\xc5\x79\x28\x96\x0d\x53\xb3\x97\x0b\xfc\x2d\x61\xa8\x4f\xc6\x8e\x58\x32\xd3\xcd\x32\x4c\x62\xa1\x80\xce\x7e\xc4\x6b\x86\x45\xa5\xb4\x54\x65\x60\xc5\x22\x01\xb6\xfd\x28\x2d\x6e\x63\x0a\x82\x8b\xbd\x91\x0b\x90\x88\x86\x89\xd9\xe5\xc5\x0a\x42\xf1\x3a\x42\xf5\x3f\xe6\x98\xa7\xb6\xa0\x64\x11\xc1\x75\x07\x7f\x27\xfc\x17\x97\x20\x5e\x45\xf5\x3c\x85\xbf\x96\x48\xe0\xc5\xae\x88\x5f\xfe\x30\x77\xdb\x23\xd9\xd9\xcb\x1a\x0f\x9f\x90\x7e\xf6\xe1\x01\x81\xe8\x84\xd8\x71\x21\x42\xa4\xd4\x1f\xcb\x77\xeb\x06\x63\x46\x19\x4e\xfc\x76\xbc\xa3\x72\xa7\xf1\x74\xea\x15\x33\x8d\xd2\xb0\x32\xa3\x11\x09\xeb\x53\xe8\x4e\xc6\x67\x69\x8b\xa7\xdb\x43\x13\x4a\x4b\x2d\x9d\x45\xb5\x25\xac\xd1\xbf\x66\xb7\x71\x46\x4f\x1c\xbc\xa6\xa0\x84\x8a\xba\x6d\x2b\xe3\xa9\x3c\xff\x0d\xdc\x9d\xcd\x53\x5f\x2f\xe2\x36\x6d\xe4\x6d\x9a\x25\x9e\x5a\x68\xb0\x5f\x0e\x8c\x4e\xc2\x6c\x60\x4a\xbe\x07\x62\x60\xe2\x89\x06\xd6\x67\x2f\xfd\xcc\x4a\x13\xdb\x3d\x82\xe4\x6c\x13\x6d\x09\xdb\x44\x2d\x85\x7d\x0c\xbf\x94\xdb\xe1\x97\x2a\xd3\x90\xa3\xda\x22\x8e\xea\x8a\x6d\xd3\x61\xdd\x41\xf0\x75\x80\xcf\x8f\x1a\x68\x5e\xe4\x4d\x0e\x98\xfa\xbf\x4c\x6b\xfd\xb0\x2f\x13\x3c\xa0\xe2\xe2\x63\xf9\xa1\x01\x20\x9f\xb0\x69\x06\x66\x3f\x11\x2f\xa5\xed\x0b\x0c\x6c\x7a\x6b\x05\x0a\x62\xc3\x5e\xce\xfd\xa0\xf7\x81\xec\x31\x38\x12\xa0\xf4\x27\x30\xe1\x59\x1a\x3c\x4b\x23\xf7\xd2\x07\xe6\xe9\x4e\x30\x37\x63\xc2\x50\xba\x6b\x33\xc8\x85\x95\x69\xd8\x19\x99\x0e\x08\x63\x67\x6e\x5f\xf8\xc5\xb3\x14\x9d\x51\x2e\x5e\x5c\x5b\xb1\x1f\x8c\x60\x13\x18\xf9\xb3\xc6\xf7\x6e\x10\x08\x14\xdd\x9a\x2d\xb4\x14\x4d\xe9\x40\x45\xbb\xd2\x26\xbc\xe9\x40\x47\xca\x42\x7b\x33\x34\x07\xe7\x1e\x2c\xad\x8b\x59\x8b\x02\x42\xce\xbb\xfa\xf2\xed\xa5\x02\x60\xb7\xe9\x8e\xea\x45\xd9\x00\xff\xf2\x7c\xb1\x40\x98\x47\x09\xef\x96\xae\x5c\x78\xd8\xd5\x57\xab\xbe\x89\x3d\xa8\xbf\xcf\xc9\xc5\x14\xf3\x60\x46\x73\xd2\xed\x63\x3e\x16\xbd\x7f\x42\x10\xed\xcb\xac\xfc\x59\xdb\x87\xe9\xb9\x78\xea\xf9\xa6\x4c\x9f\xba\x00\xd4\xf5\xad\x3b\x85\x2e\xdc\xa1\xe3\x66\xf9\xba\xec\xfb\x8f\x1d\x09\x96\xd6\xf6\x97\x6e\x87\x5d\x47\x91\x15\x57\xa3\x85\x75\x03\x4c\x06\x64\x1d\x11\x2d\x31\x10\xc3\x4e\xe4\x65\x1f\xda\xf8\xf1\x8f\x07\x47\xeb\xda\x65\xaf\xe6\x9c\x61\xb8\x86\xb5\xfd\x57\xeb\x08\xc3\x0d\x4c\x76\x58\x76\xc6\xf6\xc7\xdf\x13\x7e\x3c\xc0\x3e\x0a\x37\x43\xc9\xc8\x6b\x8e\xc0\xeb\x4b\xda\xd7\x8e\xaa\x03\xf5\x09\x77\x6d\xf7\x3b\xba\xb3\xd5\x96\xae\xda\x53\x2b\x3d\x5d\xfd\x26\xbf\xd5\x92\xc6\x36\x04\x87\x7d\xe9\x41\xc2\xc1\xb4\xcb\xb6\x95\xb7\x23\x85\x56\x52\x78\xf4\x50\x6b\x5a\x53\x84\xa2\x96\xe5\x37\xa9\x0c\x26\x99\x15\x18\xca\x99\x83\x0a\x0b\xda\x6a\x91\xbc\x35\x91\x39\xe3\xb4\x0e\x89\x0a\xc4\x2e\x99\xb5\x7c\x60\x9b\xbf\xc1\xc0\x52\x74\x34\xa8\x51\xad\x6f\x8d\x16\x2d\x0b\x06\xee\x48\x42\xee\x3e\xaa\x51\xc5\xb0\x73\x81\x00\x83\x08\x97\x36\xee\xee\xa7\xd9\x2f\x19\xda\x3c\xa5\x56\xdc\x67\x76\xaf\xee\xaa\x48\xea\x8b\x7e\x3b\xc0\xe9\x1e\x26\x94\x08\x2f\x00\xb5\x4f\x08\x42\x0f\x89\x7c\x2a\x5e\x7b\xb4\xa1\x63\x58\x01\x9f\xc6\xa5\x1f\xd3\x81\x76\x75\x46\xa8\x02\xb2\x82\x66\xe4\x3b\x1a\xa7\xdb\x1d\xda\xea\x52\x1a\xc9\x06\x05\x08\xab\x73\x20\x3d\xf5\x52\xd4\x55\xa4\xc6\xf9\xf2\x26\xf2\xa1\xfc\x38\x22\xb5\x2d\x87\x3c\x42\xf3\x18\x09\x29\x98\xa6\xce\x05\x12\xa7\x19\x15\x19\x44\x25\xb0\x90\xa9\x79\xd0\xce\x1a\x1a\xa7\x12\xf8\x8b\x6d\x69\xa8\xda\x67\x30\xb9\x3b\x18\xbd\xf3\xa9\xb1\xf3\xc2\xc6\x76\x78\xce\xf4\xff\x7e\xc1\x01\x85\xc2\xe8\x85\x27\xb6\x85\x73\x6e\x7d\xe1\x2f\x48\xc7\x9a\xb7\x43\x68\x68\xdb\x3f\xad\x9a\xaa\xbc\xda\xa6\x5d\x5a\x4f\x5b\x4d\xb3\x0a\xcb\x2e\x1f\xab\xcc\x30\x21\x4b\x7d\xee\x32\x4a\x59\x63\xd1\x84\x48\xd4\x64\xca\xcb\xd4\xa1\x8a\xaa\x64\x61\xf8\x8d\x55\x2e\x76\x2c\x60\xbc\x13\x23\xcd\xa3\x27\x08\x00\x7a\xa0\x72\x03\xca\xb8\x4b\xdf\x9e\x99\x19\xa9\x36\xff\x3b\xcd\xef\x6c\xbf\xf9\xa9\xb0\xa1\xfe\x49\x6e\x9f\x84\x7b\xf4\xb4\xd0\x20\xb5\xc8\x63\xd7\xab\xd5\x24\x9e\x5b\xbe\xab\x26\xf1\xfc\x81\xcc\xf4\xd9\x8d\x04\xa9\x03\x8b\x62\x9e\xf8\x1c\x51\x17\xbb\x5d\x49\x57\x2d\x65\xba\x01\xa0\x77\x9a\x1b\x21\x39\x41\x15\xf9\xd8\x93\x38\xdf\xec\x1b\xc3\xdb\x1f\x1e\x74\x8b\xfd\xf9\x96\x39\x03\x06\xff\xb1\xcb\x74\xfc\x50\x9b\x70\x3a\x85\x87\xc5\xff\xfb\x66\x66\xae\xf1\x13\x95\xe5\x9e\xbc\x5c\xda\xc5\xcb\x79\x65\x13\x2e\x83\x97\x6e\x67\xc6\x6a\x1f\x33\xd6\x99\x18\xd3\x2b\xcf\x5a\xfc\x16\xae\x67\xb2\x71\x78\xbc\x43\x59\x99\x09\xb2\x78\x17\xab\x68\x71\x89\xec\xd7\xde\x7c\xc9\xec\xff\x35\xbe\xa4\xfc\x66\xbe\x24\xfd\x4d\x7c\xc9\xda\xe2\x4b\x6a\xc1\x97\xcc\xf7\x12\xaa\xfc\x76\xbe\x64\x6f\xde\xa2\x5b\xe2\xf7\xe8\xb0\xc8\x71\x18\xcb\xab\x1c\x74\x46\xdb\x39\x3e\x9e\x48\xc2\x95\x69\x1e\x4b\x45\x22\xa2\xca\xad\xa4\x5e\x49\xe5\xea\x12\x5e\xdc\x22\x01\x83\x66\x1d\xc6\x45\x62\x75\xd7\x8e\xde\xc3\x71\x3d\x8a\x58\x69\xa4\xcc\x1b\xe5\xe7\x7c\x96\xbd\xb8\x9d\x2c\xdc\x83\xec\x44\x65\xf8\xc6\x5c\x18\x4e\x64\x83\x4e\x11\x4c\xcb\xf8\x6a\xd6\x4e\x52\xe3\xf8\xd3\x3b\x44\xfd\xca\x9b\xc6\x4a\xae\x9a\xe9\x1d\x8c\xde\xd3\xdb\x77\x68\x1c\x16\x83\xab\x15\xe0\x59\x28\x93\xdd\xd5\x63\x4f\x99\x74\x99\x89\x3d\xef\x12\xf4\xcf\xa5\xf0\x4f\x64\x5c\x25\x02\x81\x77\x04\x05\xd8\x6f\x32\xc8\xd4\xb5\x86\xe5\x29\x53\xc3\xf2\xbc\xa3\x61\x91\x56\x4e\x8e\xe5\x75\x59\x4d\x04\x24\xfa\xfd\xaa\xa3\x60\xa6\xab\x04\x9c\xde\x3a\x53\x2d\x1b\x9f\x63\xdc\x12\x54\x70\xe9\xb6\x45\x9a\x4f\xbc\xab\x5c\x7b\x5c\xb5\x31\x91\xcc\xe1\x4b\xb5\xa0\xfd\x82\x1c\x3e\x65\xfb\x54\xca\xf8\x04\x87\xae\x5f\x98\x6d\x73\xcf\x85\xd1\xf3\x87\xac\xd9\xd1\x6b\x2d\x6a\x04\xac\xf4\x92\xac\xba\xaf\xe7\xfb\xfb\x8e\x01\x5d\xf6\x49\x44\x4d\xab\x4d\x03\xd8\x98\x03\xe0\x34\x49\xdb\x06\x40\x35\xd4\x00\x56\xd8\x8b\x0e\x03\x23\x23\x47\xe9\xae\xc5\xc9\xc3\x3c\x81\x0e\x2f\x0e\x67\x77\x81\x09\x4d\x4b\x91\xea\x2a\xc3\xe8\xaa\xce\x67\x89\x3f\xfd\x6a\x58\x22\xfb\x6d\x0f\xde\x7c\xbf\x73\xdf\x7e\xb7\x49\x1c\x32\xe4\xd6\x7a\x3b\x81\x38\xda\x21\xd5\x9c\x96\x33\x3e\x05\x16\xbb\x3f\xdb\x99\x63\xf4\x20\xa7\xcb\x4e\xef\x48\x8d\x74\xa1\x58\xcb\x10\x5c\xaf\xc6\xdd\x49\x91\x1e\xed\xb2\x0b\xb4\x64\x61\xcb\x70\x4b\x68\x9f\xe3\xe3\x6b\xeb\x1a\xda\x8f\x1a\x9d\xe6\x95\xe1\x39\x5a\xff\xcc\x6a\x15\x9d\xcc\x62\x62\xde\xdf\x9c\xd0\x45\xd2\x99\x92\xde\x68\x0f\x65\xdf\x28\x46\x8e\xdf\x1f\xc5\x2f\x2a\xd1\xb6\x15\xc3\xcd\x38\x91\x46\xf4\xfb\xae\x30\xaa\xd2\x19\xe0\x2d\xa6\xf8\x3c\xcd\xcc\x5f\xde\x9c\xf4\x8d\x7f\xf2\xa3\x65\x88\x4e\xdf\x37\x2a\xd8\xda\xcd\xa0\x06\xe0\x42\x4f\x77\x33\x1d\x66\xf6\xac\x30\xf3\x60\xde\xa0\xe9\x03\x72\xc2\x2d\x84\x4d\x91\x4d\x3c\x78\x9c\xcd\xc5\xbb\x45\x59\x15\x4b\xd4\x5a\x0b\x08\x64\x57\xdf\xb6\x6e\xc9\x4d\xeb\x96\xc6\xde\x32\x25\x62\x43\x47\xa3\xc8\x9b\x59\xd1\xe4\xb5\xcd\xb8\x66\xbc\x0d\x79\xfd\x47\xdc\x08\x18\xba\xd8\x09\x8a\xb9\xd5\xbb\x61\xac\xd9\xf4\x39\xe3\x6c\x6b\xbb\xd6\x51\xd3\x0e\xff\xba\x0c\x3d\xed\xf5\xa3\x5b\x35\x48\x0a\xbe\x73\x85\x69\xbf\xd8\x34\xc3\xcb\xae\xac\x7c\xac\xcd\x6c\xaf\x88\x54\x1c\xe9\xc9\x4e\x06\x60\x79\x28\x4e\x7d\xbc\xce\x67\x3f\xd5\xb3\x6c\x53\x3d\x37\x2d\xaa\x07\x6e\x98\xe8\xd6\x39\x37\x57\xa8\xbb\xbb\x66\x00\x78\xb5\x95\xb3\xf1\x9f\x4e\x09\x9a\x5d\xaa\x1a\xef\x57\x47\x1a\xa4\xc7\x21\x80\xf4\x0a\x60\x20\xc3\xd0\xc1\x9d\x5f\xf4\xa3\x17\x28\xab\xbc\xd1\xba\xd6\x4d\xf4\x75\xeb\x70\x6d\xc8\xdb\xa1\x50\xb2\x2b\xdb\xaa\xab\x2f\xc9\xc5\xab\xe8\xeb\xe5\xe8\xb3\x95\xa1\x67\x2a\x38\x8f\xfd\x59\xb8\x2f\x5b\xd5\xc3\x5b\x70\xdf\xc2\x66\x98\xac\xb1\xf6\x7d\x98\x91\xbe\xda\x27\xf0\x5a\x27\xd2\xdc\x86\x4f\x99\xf6\x14\xa8\xa2\xcb\xdc\x5d\x2c\x8f\xc4\x28\x22\x19\xae\xd2\x98\xf8\x1a\x96\x75\xbb\x6b\x08\x57\x48\x54\xa1\xaf\x9c\x0c\x46\x4c\x19\xbc\x30\xd3\xc3\x21\x5e\x1a\x49\x80\xb9\xbf\xbf\xe2\x40\x27\x0a\x95\x0a\x85\x6a\x6e\x45\xb2\x53\xd2\xfc\xb0\x16\x91\xec\x90\xb1\x54\xcb\xd5\xc7\x98\x1f\x57\xfd\x3b\x3c\x34\xc2\x97\xe8\x76\xe4\x9e\x28\x0b\x7e\x8c\xcd\xa3\x2c\xbb\x23\x18\xa2\x8c\x19\x11\x06\xd6\x45\x0d\x94\xf1\x02\xd0\xd8\x1f\x2d\xdc\x15\x44\x2f\x78\x6a\xef\xa5\x0c\xd8\xb7\xa1\x76\x7a\x24\x74\x46\xdb\xb2\xfb\xda\x7f\x47\x22\xbf\x0f\x4d\x05\x7d\xdd\xdc\xb6\x9b\x59\xfa\x3d\xab\x6c\xfc\x4a\xd5\xa4\xad\x8f\x51\xcb\x83\x5d\xaf\x49\x14\xfd\x21\xb9\xeb\x1c\x1d\xcb\xa3\xed\x0e\xe2\x32\xb2\x78\xdc\x78\x1d\x79\x96\x2a\x7e\x61\x88\xb1\xdf\x47\x69\x9d\xae\xe2\x89\x27\xad\xe5\x6f\x97\x02\x74\x12\x6e\x7b\x05\xa3\x68\x89\x0a\xfe\x61\x3f\xea\x6c\xbf\xc0\xbc\xde\xfc\x3a\x46\x26\x98\xc1\x9b\x4f\x1f\x3e\x5e\x7d\xfa\xf0\x4a\x07\xcc\xc3\x6c\x7e\xa2\x3a\x26\xe5\xb8\x9b\x2c\xf2\xd5\xbb\xb4\x99\xa3\x77\xd5\x57\xfc\xe7\x16\xfe\x99\xe2\x7f\xf8\x6b\x8a\xbf\x66\xf9\x62\x21\xfe\xbc\x5d\xa5\x93\xbc\xa1\xc2\xb2\x68\x5e\xa7\xcb\x7c\x21\x7f\x7c\x40\xbc\x0c\x8f\xf8\xd9\x0c\x0b\x6f\xaa\x74\x8a\xf1\x5e\x68\x09\x08\x7d\xe8\xb2\x4f\x80\xca\x6b\xf8\x8d\x41\x0b\xb2\xea\x55\x31\x55\xcf\x6f\x72\xfd\x4c\x69\x03\xe0\x57\x49\x91\xff\xf1\x41\x75\xbf\x4a\x51\x4d\x5c\x08\x87\x53\xd9\x9c\x28\x55\x3f\xcb\xbc\xe0\x07\x91\x6f\xfd\x39\x7a\x7a\x34\xef\xd1\x2c\x03\x4a\x2b\xfc\x0f\x87\x5b\x61\x8b\x35\x54\x4a\xa7\xec\xf2\x83\x3f\x9b\x72\xf5\xa2\x5c\x94\x95\x78\xd6\x33\x87\x2d\x28\x7f\xcd\xd4\xc3\xcb\xb4\x9e\x0b\xa3\x38\x51\xf2\x73\x5e\x64\x13\x80\x47\xf9\xdb\xfd\xf4\xcf\xf9\x94\xd6\x1b\xdd\x67\x9e\x17\x93\x39\xf5\xd1\x18\xab\x84\x41\x43\x11\xae\xe1\x29\xcf\xbe\xfc\xb1\xc4\x31\x7e\x1d\xe2\x3f\xe7\xf8\x0f\xfc\x77\x8b\xbf\x6e\xf1\x17\x34\xbb\xc1\x44\x40\x2a\x1c\x0f\x19\xa2\x19\xfb\x1a\xe0\xd3\x29\xac\xcc\x3c\xb0\xb6\x30\xc0\x1f\xa7\x62\x45\x03\x73\x3f\x03\x7c\x3e\x9d\xd1\x8f\x40\xef\x2d\x17\xd7\xf0\x18\x78\xf6\x36\x68\x15\x05\xce\x6e\x07\xd6\xcf\xc0\xd8\xfb\x80\x1f\x4f\x81\x50\x0d\x0c\x30\x90\xc5\xcb\x5c\x15\x33\x44\xc8\x17\x94\x37\x23\xf0\xc2\x42\xe0\x29\x0c\x6c\xf8\x08\xcc\x5f\x81\x17\x46\x02\x4f\x61\x60\x43\x4a\x60\xfe\x0a\x0c\xb0\x09\xf0\xf1\x74\x82\xcf\x81\x05\x41\xfc\x42\x2d\xbc\x0b\x45\x01\x17\x9c\x4e\x65\x49\xe0\x80\x95\xac\xb0\xe0\xdf\x81\x03\x65\xf2\xb5\xd3\x01\x03\x9d\x7c\xf9\x05\x7f\x05\x26\x04\x52\xc2\x9d\xd3\x94\x7e\x04\x0a\xee\x02\xf1\x10\xf8\x92\x77\x3a\xf1\x87\x08\x6f\x1d\x96\x6a\xb7\x23\xcb\xcc\xf1\x71\xbd\x2d\xcd\x8e\x30\x94\x3d\x24\x11\x0d\x74\xc4\xb9\xf0\x2c\x23\x2d\xc9\x8f\x79\x5e\xe9\x74\x40\xbc\x24\x14\x7b\x25\x1b\xe8\x1f\x11\x3f\x72\x52\x12\xf5\x86\x7f\x46\x2a\xb7\x08\xbc\x50\xcf\x5c\xaa\x3e\x30\x7e\x6d\x36\xde\xe4\x2b\x7b\x67\xc3\x11\x23\xb5\x52\xe2\xc4\xad\x14\x39\x11\xbb\xeb\x0d\xf0\x4f\xd4\xa0\x63\xdf\x80\x72\xd9\x11\x51\xb5\x8a\x16\xd9\xac\x31\x8a\x7e\x86\x9f\x1b\x57\x17\x0a\xc3\xbc\x95\x26\x1b\x9f\xef\xef\x3f\x03\x69\x3f\x09\xfb\x2d\xf7\x16\x8c\xaa\xfe\x99\xa4\x3a\x47\x37\xf7\xf7\x47\x40\x87\x51\x96\x89\x9b\x24\x33\x45\xd1\x82\x86\x9a\x8a\x69\x45\x4b\x23\x71\x76\xc1\x89\xb3\x05\x70\x04\x11\xfc\xa6\x54\x7c\xc9\xe7\x28\x1d\xa4\x13\x58\x8f\xf5\x02\x9d\xe1\x45\x2a\x83\x97\x22\xa7\x21\xa5\x3d\x8a\x0a\x4b\xfb\x49\x66\x45\x2f\x4a\x56\xc1\x19\x06\x84\x9c\x59\x0c\xe0\x37\xbd\x41\x9b\x0c\x57\xf7\xd9\x65\x38\xf8\xe1\xb6\x68\xe6\x59\x93\x4f\xe8\x7b\x2d\xaf\xf6\x24\xc3\x92\xfa\x4e\x72\x4e\xa6\xf6\xf4\xbb\x95\xf2\xb8\x7c\x6b\xe4\x8e\x83\x13\xbf\x58\x94\x5f\x5e\xfd\x6d\x9d\x2e\x28\x6a\x4d\x69\x25\x00\xad\xd1\xb2\x8e\x97\x24\xbe\x5b\xe1\xc4\xa7\xef\x29\xc0\x65\xa5\x4d\x90\xe3\xbb\x6b\xce\x7a\x19\xaf\xc2\x3b\x38\x12\x5c\x9b\x9d\x34\x23\x91\x7c\xd2\x7a\x27\x32\x58\xca\x48\x40\xc0\xb6\xa0\xc0\x20\x03\x3a\x06\x1a\xbb\x98\xe3\x00\xfe\xb8\x58\x57\x11\x3d\x09\xa7\xcf\x37\x59\xb1\xe6\x82\xd7\x08\xc5\xfc\xf8\xaf\xd9\xed\xcb\xf2\x4b\xc1\x3f\xde\x94\x70\xea\x9d\x9f\x9f\x56\xfc\x43\x9f\xeb\x39\x02\xf0\x25\x59\xf0\x11\x25\xb8\xe4\x3f\x37\xfc\xe7\x16\xb9\xd5\xab\xe4\x2e\xa3\x54\x8c\x38\xff\x78\x1a\x59\x09\x86\x3d\x21\x78\xa5\x4f\x04\x3b\x43\xf4\xf4\x20\xe3\x70\xc1\xf9\x6b\x65\xbe\xb0\xac\x95\x2f\xec\xf8\x38\xfc\x9c\x64\x38\x0a\x31\x84\xfe\x88\x33\x9c\xe8\xa6\x70\x29\x62\xdf\x68\x5b\x35\xd5\x0a\xc4\xb7\x18\x6c\xc6\x7d\x6d\xac\x64\xec\x7c\xf4\x69\x25\x7c\x1a\x7a\xb4\x02\x39\xe6\x1e\xd6\x55\x9c\xd5\x33\x3e\x16\x1b\x60\x97\xe8\xc6\xb0\x1d\xdb\xbf\xf8\xca\xc8\xc5\xa9\x4f\x48\xfc\xe4\x87\xc8\x77\x3e\xe2\xef\x1f\xee\x32\xc9\x73\x0e\x47\x3c\x7c\x24\x43\xa7\xd9\x67\x03\x13\x2b\x45\xfe\xa3\x11\x0f\x7f\x24\xb1\x26\x9f\x0c\xf8\xf5\x38\x72\x0f\x06\x10\xc9\x64\xee\xfc\x68\xbf\x24\xdb\x14\x92\x66\x55\x7e\x09\xcf\xa3\xc7\x0f\xfb\x9d\xa6\x31\x6d\x1e\x9e\x3e\x9c\x64\xf9\x22\xa4\x27\xa0\x6b\xa6\xe5\x32\xec\xff\xa1\x6a\x7b\xaa\xd3\x70\x76\x59\x17\x1a\x34\x7b\x0b\x29\xb5\xd3\x62\x7e\x6a\xf2\x85\xa1\x3a\xf7\xa0\xab\xd4\xc1\x48\x2f\x80\xd0\xbb\x2e\xd3\x6a\x2a\x51\x53\xdd\x81\xb2\x5c\x54\x46\xe7\xc3\xc1\x67\xea\x25\xc0\x90\xd5\xe8\xc2\x79\x4f\x20\x2b\x5f\xae\x9c\x97\x2f\xab\xf4\x46\xbe\x9b\x39\xef\x3e\x96\x6b\x91\x85\x56\x27\xc9\x54\x2f\x3f\xfd\x24\xdf\x4c\x9d\x37\x7f\x9e\x67\xd9\x42\xbe\xd4\xc9\x96\x79\x45\x81\x62\x7a\xc1\xf1\xcd\xbd\x32\x32\x0b\xe7\xde\xb6\x44\x66\x95\x8d\x6d\x51\x5e\x76\x77\x8d\x07\x7e\x37\xb2\xbd\x41\x84\x4a\xc8\xe1\xe8\xcc\x44\xb4\xaa\x5c\xa2\x59\x7c\xbd\x41\xc9\x54\x3e\xf9\x75\xdf\x76\x5f\x50\x65\x4f\xc3\xf4\xc2\x6d\xd9\x40\x2c\xfb\xb6\x6f\x7c\xe2\xeb\x45\xbf\x6e\xf5\xb5\xba\xdd\xbf\x13\xa8\xeb\x6d\x7d\x75\xeb\x36\xbb\xde\xe7\x7e\xe3\xaf\xa1\xaa\xaf\xd1\x75\xe3\xb4\x39\x2d\xd7\xf0\xd5\x8b\x43\x96\xfd\xa5\xf1\x89\xa7\x0f\xe3\xb5\xdb\x17\x40\xfd\xde\x9d\x60\x5d\x5f\xeb\x50\xee\x69\x16\xd9\xa5\x03\x5a\xc6\xea\x1d\x8d\xc3\x2b\x6f\xfb\x98\xfd\xf5\xa0\x1e\xf0\x83\xce\x3e\x30\xf6\xb6\xa7\x97\xaf\xf9\xde\x3b\xfc\x52\xd6\xef\xea\x03\xde\x79\xba\xe0\x2c\x5a\x07\xf4\xc1\x1f\x74\x74\x42\x2f\x3d\xbd\xbc\xfd\x7c\xd8\x6a\x51\xfd\x8e\x3e\xf0\x9d\xa7\x0b\x66\x79\x0f\xe8\x83\x3f\xe8\xe8\x84\x5e\xb6\x7a\x01\x66\x60\xef\x0e\xa0\xae\xb7\xed\x72\xe5\x34\x4b\x0c\xce\xbe\xed\x32\x89\xe6\x69\x98\x5e\x38\x2d\xe7\x48\x30\xec\xdb\x32\x51\x17\xbe\x96\xe9\x85\xd3\xf2\xaf\x82\x84\xda\xb3\x6d\x49\x71\x79\x5a\x17\xaf\xda\xed\xbf\xab\xb2\x7a\xef\x65\xf9\x57\x59\xdf\xdf\x03\xbd\x6b\x77\xf1\x69\xef\xed\x64\x02\xd1\xdf\xf8\x27\x77\x43\x17\x65\xba\x37\xf2\xf9\x19\xeb\x7a\xda\xc5\x72\xa7\xd9\x0c\x1d\xb1\xf7\x6d\x97\xbc\xb6\x7d\x0d\xd3\x0b\xa7\xe5\xa5\x22\xc1\xf7\x6c\x5d\xd3\xec\x9e\x1e\xd4\x4b\x5f\x2f\x6f\xca\xfd\xb1\xcd\x1b\xf5\x41\x57\x2f\xf8\xd2\xd7\xcb\xdb\xfd\xc1\xfe\x8d\xac\xdf\xd5\xc7\xdb\x16\xf0\x73\x17\x07\x60\xb4\x37\xea\x83\xce\x4e\xda\x38\x6d\x29\x58\x9c\x43\xfa\xf0\xc3\xa8\x78\xe5\xb4\xbf\x4a\xeb\x66\xef\xad\x78\x47\x95\x3d\x6d\xd3\x0b\xa7\x65\x76\x0f\xdd\xb3\xe5\xf7\x54\xd9\xd3\x32\xbd\x70\x5a\xe6\x74\x31\xfb\x36\xcd\xc9\x5a\x7c\x6d\xf3\x1b\xb7\xf1\xf5\xf5\x72\xff\xeb\xf6\x03\xd7\xf6\x35\x4e\x6f\x9c\xc6\x1b\x24\xe2\x5f\xa0\x3a\x7f\xef\xe1\x7f\x34\x3e\xf1\x74\x63\xbc\xf6\xf5\x75\x00\x01\xf4\x51\xd6\xef\xea\xa5\x4d\x02\x51\x17\x87\x9c\xe5\x8f\xea\x83\xae\x4e\x3c\x67\x99\x7a\x39\xe8\x5e\xff\xa8\xbf\xe8\xea\xc7\x77\xb3\x7f\x41\x5e\x69\xdf\x3e\x88\xb1\xf2\x35\x4f\x2f\xec\x96\x37\xd1\x75\x72\x27\xc5\x21\x57\x03\x64\x92\x50\xa4\xc8\xb4\xf2\xd5\x80\xb8\x9b\xc8\x91\x72\x5c\x0d\x0c\xd6\x84\x5f\x02\x47\x80\xa5\xab\x5b\xfa\x09\xc8\x0a\x7e\xad\x49\x38\x69\xd2\xde\x57\x03\x83\x78\xa7\x97\x48\x33\x43\x29\xfc\x91\x3f\x71\x9b\xb9\x04\x9e\x74\x21\xd2\xa6\xb2\x18\x9e\xd5\x0b\xa4\x27\x45\x39\x3c\xca\x62\x26\x01\xb9\x9c\x9e\xe5\x0b\xc2\x71\x5c\x8e\x8f\xb2\x98\x37\x84\xcb\x59\xf6\x4c\x2f\x80\x42\xc2\xb2\x72\x85\x3f\xf9\xc2\xba\x1a\xd0\x2d\x17\x29\x61\xd4\x15\xcb\x7f\xb1\x80\x09\x94\xab\x01\x51\x35\x91\x21\xc7\xb9\x1a\x08\x72\x44\x14\x32\x25\x40\xa5\xf4\x18\x29\x09\x0f\x95\x7d\xa2\xfe\xe8\xe2\xbd\x1a\xe0\x5d\x1d\x59\x52\xa8\xab\x81\xba\x0e\xd5\x0b\x02\x5c\xf1\x02\x9f\xd5\x8b\xb7\x34\x22\x79\xe7\xe8\x62\x5e\x07\x75\x51\x44\x86\xc8\x4a\x14\xf3\x28\x18\xaf\x5e\x0d\x08\x19\x63\x01\xa3\xc3\x2b\x36\xcd\xc0\x02\x81\xc4\xae\x44\xaa\x2c\x2a\x62\xd4\x73\x35\x60\x8c\x85\x45\x26\xae\xb8\x1a\x18\xc8\x46\xbd\xe4\x8d\x97\xa8\x41\x15\x8b\x99\xa9\xf3\xac\x5e\xc8\x3d\xd3\x67\x10\x5f\x31\xec\x5f\x0d\xe8\xc0\x6c\x94\xb9\xd5\x2b\x8c\x43\x72\xdd\xbf\xbe\x78\x75\x39\x30\xe5\xa2\x09\x14\x90\x38\xe7\xab\x25\x9d\xbc\x8a\xb2\xaf\x19\x00\xb0\x92\x47\x77\x04\x84\xce\x07\x4e\x3d\x19\x4d\xbc\xa2\xec\xca\x94\x12\x08\x95\x44\x52\xdc\x23\xac\xe6\x06\xab\x8a\x3a\x7b\xc9\x81\x4f\x28\xcf\xf1\x2e\x71\x28\x7b\x64\x5c\x63\x44\x04\x14\xc7\xe7\x2d\x59\xfd\xcd\xc8\x91\x98\xde\x0e\x14\x4c\xea\xdf\x04\x55\xfa\x27\x03\xb5\xfe\xcd\xbb\xab\x7f\x8b\x9d\xbc\x49\x6a\x53\xee\x79\x3b\x30\xe1\x58\xe4\xdb\xfe\x6c\x24\x0b\xa5\x41\x59\x55\xb5\x3c\xf3\x56\xcb\x33\x6f\x92\x49\xab\x59\x42\x44\xfa\x27\x1f\xb2\x9b\x64\xdd\xaa\xc8\x28\x05\x3a\x3f\x87\xce\xab\xc1\xf5\xba\x69\xca\xa2\x63\x00\x2d\x19\x2d\x95\x9a\xa8\x49\x97\xea\x83\xe6\x94\x11\x24\x3a\x65\x6f\xad\xc5\xd5\x47\xcb\x29\xa3\xb9\x2e\x5a\x53\x20\xf4\x67\xff\xc4\x53\xe0\x96\x34\x56\x83\x0a\xed\xd9\x45\x8c\xf2\xec\x32\x67\x28\x1a\xd3\x99\x65\x25\x8e\x6d\xd5\x1a\x9b\x79\x60\x9d\x52\x7b\x8c\xfa\x94\x3a\x65\xdc\xd5\x4d\x32\x6b\xb5\x2d\x50\xc6\x4d\x32\x6f\xbd\xe2\xf3\x7b\x93\x4c\xdb\xfb\x8d\x97\x8c\xf1\xd3\x5a\x79\x46\x53\x37\x49\xba\x59\x86\x37\x6c\x7a\x73\x95\xdc\x18\xca\xa9\x9c\x4e\x91\x4a\xbe\xbb\x5d\xf5\x74\xd5\x8f\xae\x2c\xc9\xf0\xd7\xdd\xf2\x75\x43\xd4\x1b\x7f\x7f\xbe\x4d\xee\xde\x25\xe6\x8d\x87\x8f\x9e\x44\x7e\x99\x2b\xbc\xfa\x61\x8b\x58\xde\x27\xff\x8d\x87\x8f\xcf\xa2\x6e\xf1\x2f\xbc\x3e\x8f\x3a\xa4\xbf\xf0\xce\x1e\xa8\x21\xe0\x85\x77\x8f\x22\x9f\x7c\x17\x5e\x3c\x8e\x3a\xc4\xbb\xf0\xee\x49\xe4\x93\xee\xc6\xc3\xef\x9f\xf8\xad\x9c\x6d\xad\x41\xcb\xaa\xe6\x70\xef\xea\xdc\x34\x66\x63\x83\x34\xc3\xc9\xad\x25\x59\x2f\x13\x32\xbc\xa0\x15\x7b\x99\x36\xa9\x27\xf4\x6f\x60\x55\x20\x7d\xf7\xb8\x19\xd8\x5f\x09\x85\xb4\x55\x08\x90\x95\x0f\xd2\x35\x85\x22\x22\x2b\xa5\xb0\x42\x17\xf7\x96\xdf\x93\x67\xb3\x69\xee\x87\x84\xd9\xfe\xd6\xb9\x63\x1e\x6e\x91\xf1\xfb\x37\x8d\xf5\x10\x0f\xe4\x83\xc6\x6a\x29\x2b\xc4\x80\xd9\x60\x05\x50\xde\xb7\x0c\xdc\x81\x7f\x1a\xfd\xe1\x01\x8a\x85\x51\x28\x63\x12\xc0\x14\xb3\xfc\x46\x3a\x66\xca\xd2\x37\x64\xf2\x92\x64\x5c\x5a\xa4\xa4\x4e\xc3\x7e\x93\x42\x2a\x96\xc8\x36\x54\x26\x45\x2c\xab\x01\x39\x34\xcc\xd2\x49\xa6\xe8\x99\xbc\x3b\xff\x48\xae\xe2\x70\x56\x18\x28\x0f\x1b\x83\xbf\x49\x39\x2e\xc3\xa2\x1f\x17\xf0\x2c\x42\x12\x0a\x17\xf8\x81\x08\xbf\xf6\x8e\x69\x92\x6c\x3a\x6e\x17\xc5\x68\x7c\x8a\x30\x4f\x11\x96\x88\xb6\xe1\xcc\x1e\x79\xfd\xd2\xa9\x9a\xd4\xe3\xd4\x8c\x18\xfb\xb1\x5a\x67\xb1\x55\xf2\x3a\x5d\xd4\x62\xf6\x79\x6d\x50\x46\x1f\x00\x8f\xaf\xa0\x81\x76\xe5\x9d\xee\xa8\xae\x5d\x75\xea\xf7\x21\xad\x6d\x25\xd3\x47\xb2\x44\x20\x35\xda\x1d\x25\xe2\x61\xdb\x51\x2a\x8d\xeb\x48\x38\xa6\x70\x2d\x7b\x0a\xbf\x50\x9e\x67\xc2\xef\x78\x75\x08\xeb\x47\xe2\xc1\x6a\x11\x59\x99\x6e\x4e\x54\x46\x8b\x56\xf3\x25\xba\x29\x2d\x57\x1e\x44\x82\x61\xee\xe5\xeb\xfb\x7b\x8c\x32\x37\x28\xca\x2f\x21\xa9\xf0\xdd\x7d\x20\xb7\x7f\x5c\xd4\x5a\xfe\xdc\x8c\x4a\x3b\xec\x97\x4d\x5c\xb6\x4d\x96\xdd\x0d\x3b\x3a\x1b\x19\xe9\x30\x0c\x80\x1c\xb9\x84\xea\xb8\x4d\xb9\xc6\x8d\x05\x19\x32\xa2\x94\x07\x2e\x5a\x50\xb1\x89\x1c\xd2\xb8\x23\x41\x87\x3d\x22\xe7\x9b\xb1\x87\xc0\x8e\xd1\x81\x01\x97\xff\x8f\xb4\x23\xe8\x18\xb6\x27\xb4\xf1\xb0\xd0\x12\x1c\x18\xec\xd6\xca\xc1\xf7\xfc\x06\x0f\xab\xe7\x3b\xf3\xbd\x0f\xe4\xfd\x76\xe4\xc6\x4c\xb7\x9f\x79\x11\x4b\x91\x0e\x34\xa6\x3a\x40\x12\xd7\x87\x6f\xb4\xe7\x8d\x83\x72\xf4\x0b\x0b\xeb\x90\x87\x2e\xea\x4c\x55\x97\xc9\x1a\x7e\x99\xc8\xd3\x1b\x48\x83\x50\x74\x95\x88\xb3\xc7\xaa\xf8\xb0\xd0\x90\xd8\x47\xc0\xe4\x04\x0b\xa2\xc0\xfc\x91\x58\xaf\xcc\xa9\x23\xc2\x34\xc6\x52\xa2\x4f\x5b\xa1\x0b\x22\x6a\xc7\x1a\x5d\x61\xfd\x74\x7d\x8a\x1b\x28\x68\xe6\x55\x96\x3d\xaf\x6e\xc8\xfc\x8a\x50\x08\x86\xfa\x70\x9d\x8f\x3b\x2a\x7e\x7b\x9c\xb7\xb6\x2f\x71\xd4\xc6\x3f\x40\x04\xd1\x65\xf9\xf8\x10\x17\xe3\x83\x2e\x4b\xad\x83\x2f\x31\xf6\x02\x52\xbd\x53\x81\xd6\xbe\xe5\xaa\x34\x49\x3e\x1a\xf8\x01\x1e\x68\xff\xb7\x29\x92\xc7\x87\x84\xae\xff\xe6\x45\xee\xb2\x65\x48\xed\x37\x40\x92\xb7\x6f\xa5\x37\xe5\x14\x43\xd8\x57\xc2\x31\x15\x2f\x27\x20\x86\xe3\x34\x5a\x88\x00\x95\xe2\x82\x69\xaa\x05\x86\x64\xa4\x1f\xf5\x3c\x9f\x35\xea\x57\xba\xd0\xcf\xcb\xac\x49\xd5\x8f\x2a\x5b\xc1\x21\xe5\x67\x6c\x4d\x5e\x4e\xd0\xb5\xd5\x2b\x5e\x7e\x62\xd0\x3e\xba\x17\x86\x83\xe6\xb4\x75\x40\xf9\x20\xf0\xf8\x8e\x31\x69\x4a\x7c\x46\x3a\xab\x2d\x5f\x01\x29\x5c\xe8\x8f\xee\xef\xb1\x6c\xbd\x32\x9a\x69\x06\xb2\x81\x33\x94\x79\xe6\x96\xe0\x65\x67\xff\x07\x77\xe1\x01\xa5\xf5\xbe\x80\xbf\x95\x9f\x31\x37\x18\xca\xbe\x8f\x3a\xf7\x17\xde\x12\x47\xf3\xf8\x10\x7b\xdb\xdf\x06\x97\xff\x96\x67\x5f\x70\x7e\x6f\x32\x6c\xba\x6e\x83\xa5\x0b\x81\x75\x72\x57\x03\x7a\xcf\x8a\x7f\x17\xd0\x46\x3f\xfe\x22\xe0\x90\x52\xc1\xfe\xbb\xf9\xe3\x2f\xdf\x0e\xa1\x2d\x48\x4c\x23\x16\xec\x78\xdc\xd2\x1b\x21\xf3\x11\x4c\x7d\x40\xf0\xc2\x6c\x58\x16\xa3\x50\x28\x1b\x9f\xc7\x8f\xe8\xef\x10\xe1\x89\x6b\xd7\xf2\x28\x98\x58\xd0\x4b\x93\x59\x55\xee\xef\xc3\x66\x80\xa9\x17\xa5\xef\x30\x02\x54\x5d\x4d\xc4\x4f\x00\xab\xa6\x94\x06\xbb\x56\x45\x0c\x92\x9a\xde\x64\xff\xee\x03\x64\x7a\x21\x19\x47\xae\x45\x0c\x24\x2e\xe8\x89\x0a\x4e\xc0\xd2\x12\x32\xe3\xa5\xa6\xfe\xd2\xd5\xd4\x5f\xcc\xa6\xfe\xa2\x9a\xfa\x8b\xdb\xd4\xc7\x72\xe5\x03\xfd\xfa\x10\xd0\x77\x81\x08\xca\x7f\xd8\x03\xca\x0f\x88\x6b\xfa\x3b\x61\x5f\x17\x98\x53\x54\x77\xac\x51\xcc\x63\x92\xfb\x1f\xcd\xa2\x09\xd9\x63\x4e\xad\xb2\x4e\x88\xdd\x02\xe5\x2d\x60\x2e\x3d\xab\x9e\x7e\x0b\xc2\xe9\x58\xdd\xc3\xb3\xc6\x1e\x7c\x0f\xfb\x19\x28\x58\x54\xf4\x2f\x70\xd3\xa4\x37\x03\x2c\xd5\x11\xc6\xf1\x97\xb0\x2b\x2f\x45\xc4\x6d\x66\x42\x29\xc1\x39\xcb\x4a\x28\xf4\xb6\x4a\x60\x2e\x43\xb6\x51\x70\xb6\x97\xc2\x7c\xde\x88\x7b\x22\xb9\x19\x04\x47\x8c\x26\xc0\x96\xf2\x7f\xa6\x96\x84\xf0\x05\xb9\xa8\x26\xcd\x17\xfe\x43\xce\xef\xee\xef\xbd\x97\xc1\xd6\xbd\x69\x59\xc6\x7a\x69\xba\xbf\x9b\xa0\xaa\x25\x00\xc9\x16\x4d\xea\xc5\x32\xfc\x46\xe2\x06\x51\x2f\x20\x05\xc9\x4b\xe3\xd5\x69\x33\x30\xca\x62\x0a\x8b\x0c\x4f\x5e\x6c\xc3\x6f\xac\x26\xff\x62\x36\xf9\x17\x4f\x93\x56\x05\xcf\x7b\xd5\xe3\xff\xe4\xd3\x43\xcf\x6f\x64\xa6\xdc\xdf\x41\x9c\xf3\x78\xbf\xa0\x7d\xbe\x24\x60\x1d\x11\x10\x5a\x1c\x62\xd3\x76\x29\x66\xce\xce\xef\x6e\x2c\x03\x20\x7c\xe1\xdf\x3f\x41\x1f\x28\x20\x1c\xfb\x0a\x95\x0b\x75\xec\x7b\x8b\xf9\x69\x39\xa8\x69\x5e\xff\x54\x98\x6e\xa3\x47\xc3\x4d\xe4\x16\x62\xa6\xac\x0e\x07\x68\x21\x60\xb0\xab\xb7\x2c\xaa\x8f\x8e\xbc\x9d\x75\xf9\x17\x63\xcc\x85\x28\x8d\x6a\xa0\xae\xee\xaa\xf0\x48\x30\xd3\xd6\xa7\xa1\x88\xc4\x37\x89\x16\x46\x3a\xd7\xd6\x64\xce\xa2\x89\x66\xe7\xd5\x96\xa0\xcf\xee\x19\x19\x34\xf3\xd9\xb1\xbb\xc4\x4f\x74\xfa\x57\x6c\x9c\x52\x37\xa8\x5e\xc8\xb7\x9c\x9b\xd8\x4c\x48\x89\xb7\xea\xdf\x6d\x32\xe0\xd8\x7b\xad\xf7\xaa\x95\xae\xb5\x96\xc1\xfe\x17\x68\xdc\x66\x8c\xcf\x4e\xc6\x27\x39\xfa\xa4\x0b\x6a\x22\x60\xaf\x47\xc5\xd3\x4c\x86\x65\x30\xc2\x44\x50\x4a\x25\x35\x78\x07\x0e\xe0\x5d\x52\x0e\xde\xfe\xf1\xc3\xab\xf7\xff\xf6\xea\xe5\xd5\xab\xf7\xef\xdf\xbe\xf7\xc2\x18\x56\xac\x8c\x25\x1c\x9b\x3f\x34\x06\x12\x31\x8b\xe4\xb4\x65\x36\x5b\x4f\x63\x49\xab\x5f\xbd\xc2\xf6\x4e\x15\x27\x43\xb9\xd0\x39\x2c\xf4\x66\x23\xdc\xfb\xdd\x55\x12\xa9\x4e\x3d\x80\xf2\x1b\xd6\x2f\x87\xbb\x8a\x72\x8c\x88\x83\xd9\x9e\x09\xad\x6d\x8e\x50\x56\x1f\xb5\x27\x75\x7c\x9c\x32\x40\xa8\x07\x03\x5d\xd7\x88\x2c\x0c\x58\xc3\x14\x67\x1e\x38\x33\x16\x60\x4d\x0b\xb0\xf5\xbc\xc3\xf2\x94\x32\xcd\x75\x1e\xd9\xa3\x89\xef\x7c\xee\x7c\xed\x18\x84\x8f\xf7\xcb\x7f\x78\xd7\xa2\x38\xe3\xb3\xc8\x25\x1d\xa1\xa8\xca\x66\xc0\x7f\xcd\xb9\x88\x04\x7f\x76\x12\xc9\xaa\x4d\xba\xc2\xd1\xfc\x1a\x55\x2d\x3a\x14\x8a\x6f\x37\xbe\x6c\x77\x8f\x0f\x93\xbd\x73\x3a\x39\x49\x4d\xf4\x45\x4a\xb9\xc6\x25\x24\xdc\x9c\x21\x51\xe5\x14\x65\x66\x88\xb0\x6a\x1c\x72\x36\x84\x01\xec\xcc\xe2\x96\x43\x8b\x00\x9f\x59\xc8\xf2\x90\x7f\x57\xe3\x8b\xe6\x12\x25\x58\xb0\xa7\x18\x72\xeb\x02\x2a\x5a\xe9\x1d\xfc\x51\x30\xab\xae\xdd\x7a\x72\x58\xac\x39\x7d\x1a\x86\x00\xf6\xb0\x3b\xc9\xd9\xa8\xd2\xf9\x8a\x2a\x00\xfd\x2c\x09\xb3\x13\x40\x8e\x82\x4f\x7d\xde\xa0\xae\xfe\x9f\x72\xa8\x0e\xc0\x98\xc1\x93\x8a\x6f\x7a\x5f\x3c\x7d\x3a\x7c\x22\x06\xff\xe4\xf1\xe3\xf3\xa1\x67\x73\x9e\x78\x04\x3e\xf6\x98\x0c\x26\x8a\x42\x36\x85\x79\xd4\x11\xd1\xb7\x29\x3f\x21\xd8\xbf\xc0\x58\x0b\xfd\x8d\xa4\x75\x1e\x9c\x86\x83\xfe\x83\x1b\x5f\xdf\x87\xe5\x1e\x54\x2e\x53\x7a\x28\x65\x14\x2c\xeb\x53\xcc\xee\x63\x6c\xd1\x24\x5d\x66\x88\xa0\x88\x98\x7a\xf0\xbf\x4e\xa1\xc6\x83\xf6\x5e\xa9\x5a\x31\xac\x01\x8d\xc6\xc3\xb6\xbb\x90\x29\xd7\x02\x68\xdc\x71\x43\xec\xe8\xd1\x59\x8c\x5e\x98\xe3\xa3\x21\xfc\xcd\xfa\x63\xaa\x28\x68\x57\x74\x30\x25\x09\x76\x59\x00\x65\x5a\x60\x70\x37\xf9\x18\x8a\x17\x4b\xac\x29\x89\xe1\x77\x65\x9d\x93\x20\xfc\xe8\x28\x1c\x3e\x39\xee\x7c\x8f\x31\xd9\xe0\xde\x87\xff\x5b\x90\x49\x7e\x5b\xbf\x90\x74\xca\x03\x9a\xfa\x6d\x3c\xfc\x91\x88\xa8\x27\x1e\x0e\xce\xb7\xe2\x40\x21\x1c\x1f\x1b\xf9\x74\x64\x78\x09\x33\x17\xaa\x2e\xed\x1f\x1f\x07\x0c\xae\xc2\x6d\xf8\x08\xdd\x89\x39\x90\xd7\xe7\x74\x41\x85\x58\x47\xe4\x9c\x31\x92\xa8\x62\xb6\x18\xb4\xd9\x81\xce\xdc\xc3\x0d\x5d\x21\x6a\xce\x32\xfa\x1c\x7e\xe5\x4d\xb6\xe4\xa6\xfc\xd9\x81\x71\xf8\xe3\x56\x5a\x21\x60\xf3\x29\xce\x4d\x3f\x26\x21\x13\x1c\x75\xd3\x29\xb5\x29\x9f\x73\xfa\x9c\x76\xde\x4c\xf9\x2a\x3e\x3f\xa3\x90\xe0\x4f\x0e\x61\xcf\xa4\x90\xa3\x14\x82\xf5\xd7\x29\x8a\xc6\x09\x67\x15\x89\x8c\x17\xcd\x94\xf0\x5d\x93\xde\x50\xb2\xeb\xc6\x3e\x4c\x11\x8a\xff\x17\x29\x27\xc2\xe6\xa0\x25\xaf\x01\x2d\xbe\x4b\x6f\x74\xa0\xef\xe0\xa4\x89\x26\xf2\xc7\x9f\xf3\xc5\x42\x84\x8e\x34\x49\xbe\x14\xe3\x38\x6f\x44\x88\x5e\x8f\x77\x9d\x8c\x08\xca\x79\x94\x37\x1a\x83\xb6\x02\xea\xfb\x12\xdc\xb4\xc2\x19\x6f\x45\x96\x46\x33\xf1\x0f\x3a\x87\x8f\x1b\x7a\xcd\x83\x53\x3d\x8c\x98\x6f\xbd\x9b\xc1\x92\x2e\x66\x1d\xb4\x19\x79\xd3\x8b\xe1\x25\xac\xed\xcf\xe5\x17\x85\xa8\xdc\x60\x9d\x7c\xbf\x4c\x46\xeb\xf0\xe8\x68\xc2\xa4\x2c\x26\x5e\xc5\xa0\xfd\x49\x7e\x7c\x5c\x87\x9c\x1a\xac\xec\xdf\x15\x40\x0e\x01\x33\xfb\xa7\x8f\x6f\x7e\x4e\x4a\x68\xf8\xa4\x39\x29\x2f\xce\x2f\x15\x51\xb3\x80\xd2\xb3\xcb\xd1\xe2\xf4\x74\xd4\x2f\x92\x62\x00\x93\xe5\xc4\xe3\x4c\x92\x9a\x9f\x37\xd4\xcf\x2a\xa1\x88\x68\x62\x0d\xea\x3f\xde\x7e\x64\x78\x80\x23\x34\xa9\xf2\x15\xae\xe3\x4a\x5c\x06\x70\x4a\xd6\x78\x69\xa5\x40\xe2\x0e\xa0\xc3\x57\xe9\x04\x2f\x31\x4d\x51\xcd\x92\x34\x2c\x06\x94\x16\x16\x8f\x7d\x8d\x21\x04\xd5\x00\x60\x3c\x56\xf6\x74\xe3\x95\x5a\xad\x99\xe5\xb1\x4d\xc6\x71\x39\xba\xee\xeb\x9c\xe8\x6a\xa3\x19\x86\xe9\x8c\x60\xa8\x79\xa0\x70\xb2\xa9\x25\x0e\xe7\xc0\xc6\x48\xd2\x75\xa5\xd0\x2e\x51\xd1\xf7\xa9\xce\x5e\xbe\x7d\x33\x56\xce\xf5\xdc\xae\xf4\x96\x0f\xa6\xf9\xe7\xa0\x2f\x64\xde\x80\xd9\xff\x5a\xff\xe1\x69\xf8\xd7\x2f\x27\xfd\x07\xed\x13\xeb\x1d\x6f\xfc\x3d\x19\xbc\x78\x47\x0b\xd7\xc0\xa3\xa8\x35\x58\x80\xb9\x2e\x28\x3c\xcc\x76\x43\x82\x95\x48\xad\x00\x28\xac\x15\xaf\x07\x0b\xc9\x07\x9a\x43\x2f\x0a\xfe\x5c\x12\x74\x79\xfd\x4b\xfa\x8b\x41\xd4\x54\xf7\xf7\x68\xaa\x07\x1f\xb5\x72\x2b\x22\x7e\x2d\x01\xb9\x8d\x83\xe0\x24\x8b\x55\xe2\x2e\xdd\x11\x46\xfc\x4c\xe0\xbe\xae\xf2\x25\xd0\xe0\x51\x76\x12\xac\xbe\x06\x76\xd6\x9f\x0f\x1f\x8c\xf8\x35\x00\xf7\x80\x46\x31\x26\xc7\x22\xab\xeb\x5f\x08\x73\xb7\x0f\xb4\xf9\x4d\xcc\xc9\x3d\x9e\x78\x88\x55\xef\xa5\xee\x89\x85\xbc\xb1\xc3\x17\x6e\x72\x53\x0b\x9b\xb0\x82\xcf\xd6\xca\xc2\x21\xc5\x30\xf5\xb9\xab\xce\xc5\xf2\x33\xa7\x1c\xd5\xfe\x50\x2e\x62\xd6\x5b\x5f\x00\x06\x4c\x3c\xe3\x81\xe2\x8d\x5d\x53\xea\x16\x13\x8b\x60\x96\xc3\x8f\xda\xde\xc8\x4f\x76\x51\xc2\x82\x76\xf7\x51\xd1\xdf\x1f\x46\x49\x4a\xeb\x38\xbc\xe3\x7c\x37\x64\x08\xb0\xd1\xf4\x15\x21\x95\x46\x95\xcc\x0c\x71\x17\x1c\x07\x71\x70\x9c\x2e\x57\xa3\x20\x0a\x9e\xe1\xf3\x4d\x83\x8f\x4f\xf1\x71\x81\x8f\xdf\x05\xdf\xc1\xe3\xdf\xd6\x25\x95\x7f\x87\xe5\xff\xf8\xf5\xfc\xfb\x51\xb0\x01\x84\xf0\xe0\xe2\xf8\xd9\xd3\xe0\xbb\x4b\x8b\xe4\x93\x2b\xf0\xfd\x21\xfa\x45\x9d\xba\x9b\x59\x00\x8e\x7c\x5c\xd3\x4d\x1e\xe7\x08\xf5\xf8\x48\x51\xd1\x11\xc3\xe1\x59\x56\x71\x0c\xe1\x7a\x0f\x53\x11\x75\xb9\x11\x51\xd6\x3b\x92\xb7\xf3\xcb\x3e\x47\xf7\xa5\x1b\xb2\xbf\x11\x36\xba\xfb\x44\x11\xb4\x22\x25\xdb\x17\x22\x45\x22\xf6\x5e\x87\x12\x35\xe6\xb5\x20\xd8\x6c\xaf\xe7\x4d\xc7\x6d\xd9\x15\xf6\xaa\x33\x34\x29\x8f\x00\x8a\x1e\xf9\x6d\xf3\x44\xff\x40\x12\x0e\x7d\xc6\x79\xdf\x1f\xae\x62\x15\x92\x37\xe4\x9e\x5b\xf6\x4c\x05\x5c\x9c\xc7\xc7\x4a\x4e\x1c\x56\x28\x6d\xc8\x5c\x12\x4e\xe5\xac\x54\x3c\x5f\x23\x24\xcd\x70\x30\x24\x5c\x43\x77\x15\xf2\x70\xd9\xe6\xce\x24\xe1\xaa\x14\xe3\x34\x21\x6b\x4e\x77\x19\xac\xd6\xb6\xb5\x95\xd4\x9d\xe7\x2b\x58\x81\xef\xbd\x2b\x72\x58\x30\x1d\x92\x18\xb0\x5b\x41\x28\x05\x05\x19\x0a\x0a\x3c\x07\x7c\xbf\xc8\x09\x6e\x15\x0f\x91\xab\xa8\x01\x78\x1f\x23\xaf\xc2\x72\x8d\x02\x83\x70\xfa\x30\x8b\x87\x98\xb5\x02\xcd\xe2\x24\x64\x54\x41\x79\x33\xa7\x66\xec\x88\xfb\x7b\x55\x7e\x5d\x4e\x6f\xc5\x3c\xf5\xf9\xb5\xdf\xfa\xe6\x7e\x88\x6c\x5d\xd0\x77\x28\x17\x92\x0a\x60\xa9\x37\x94\x5c\x31\xcb\xa4\x43\xa4\x01\x65\x51\x44\xb7\xe5\xf1\xf1\xf0\x21\xfc\x2d\xe8\x06\x1c\x3e\x04\x3e\x2a\x4b\x8a\x28\x7b\x96\x3c\x3c\xbf\xbf\xa7\x57\xd9\x18\xd5\xc9\x9e\x21\x1e\x72\xdf\x0b\x95\x09\x8c\x4e\x11\xff\x17\xf4\xf3\xf2\xfe\x9e\xfe\x52\x86\x52\xb8\x50\xa7\xb0\x2a\x94\xe5\x1e\xd3\xe2\x6a\x65\x09\xc6\x1e\xf2\xe8\xc6\x8d\x70\xcd\x8a\x0e\xe0\xf9\x8c\x03\xb2\x2d\x0f\x62\x4e\xc3\x41\x5a\x4b\xa9\xca\xc6\xb8\xca\x07\x28\xee\xd3\x0b\xb5\xac\x30\x5a\x7b\x90\x71\x10\x98\x54\x82\xc7\x2c\x02\xee\x8f\x57\xf5\x24\x0e\xe0\x9f\x74\x95\x05\xd1\x87\x15\x5c\x2f\xd7\x69\x15\x07\xbd\x20\x22\x31\x54\x00\x90\x5a\x7e\xc1\xc7\x20\xfa\xb4\x12\x3f\x3f\xad\x82\xe8\x7d\x7e\x33\x97\xaf\xe9\x39\x88\xc8\x76\x9f\x4b\xf0\x11\x0a\xb2\x45\x1c\xc0\x3f\x59\x03\x6d\xff\x39\x87\x97\x6f\x3f\x04\x11\x39\x03\x04\x86\x67\x40\x10\x3d\x5f\xad\x6a\xa7\x48\x98\xaa\x07\x42\x92\x55\x4e\x7e\x85\x2f\xcb\xff\x7a\x07\x0b\x46\xa1\x66\x50\xd9\x67\x4f\x17\xaf\xb3\xbb\x1f\xe2\xe0\x8f\x18\xa2\x17\x27\x12\x44\x3f\xc6\xc1\xc7\xf4\x3a\x88\x86\xe7\xd0\x3a\xd0\x6f\x15\x3c\x3e\x8c\xc5\xea\xc3\x0d\x0f\xcd\xa3\xe2\x10\x1e\xbf\xe7\xee\xa1\x2f\xf8\x01\x8d\x3c\x5f\x60\x29\x7c\xff\x2e\x05\xb0\x09\xa2\xf3\x33\xa8\x90\xae\x6a\x1e\xc8\xf9\xf7\x7a\xcd\x1e\x9e\xd3\x6a\x3d\x7c\x88\x75\x6f\x32\x5c\x9b\x87\x8f\xf8\x99\x57\xe1\xe1\x63\xec\x71\x0a\x0f\xd0\xdf\x9f\xca\x25\x7e\xf3\xbd\xb5\xb0\x0f\x7f\x30\x16\xf6\xe1\x8f\xf6\xaa\x3e\x3a\xb3\xd6\xf4\x11\xb4\x06\x17\x48\x86\x61\xdb\x1e\x3d\xd1\xcb\x3b\xc4\x39\xbe\x1e\xe2\x03\x8c\xe4\xf5\x39\x3e\xc0\x30\x5e\x3f\xc4\x07\xf8\xe6\xf5\x23\x7c\x80\x0f\x5e\x3f\xc6\x07\x18\xc0\xeb\x27\xf8\x00\x5d\xbf\xfe\x1e\x1f\xa0\xdb\xd7\x3f\xe0\x52\x41\x7f\xaf\x7f\xc4\x87\x21\x36\x78\x86\x4f\xd4\x34\xb6\x7d\x8e\x6d\x0f\xb1\xf1\x47\xd0\x38\xd0\x96\xbc\x1e\x18\xb9\xc5\xda\xa9\xf3\x73\x78\xfd\x26\x6b\xd2\xc0\xc5\x61\x5d\xd6\x1b\x74\x6a\x0f\xcb\x9b\xa4\x25\xd1\x11\xaa\x2a\x4d\x73\x45\xbc\x95\x06\xae\x1a\x58\xf9\xa8\xb4\xde\x84\x22\xc5\x43\x85\x27\x5f\xe5\xb8\xae\xc6\x47\x47\xc5\x45\x75\x89\xa2\x1b\xbf\xdc\x42\x12\x61\x00\x2d\x71\xc0\x9a\xea\x20\x12\x70\x14\x07\x42\x43\x8d\x10\xdf\xa4\x71\x20\xb4\xd7\x00\xda\x08\x73\x71\x20\x75\xd6\x81\x2f\x14\xce\xf7\x87\x25\xaf\x91\x3c\x74\x23\x6c\x26\x4c\x13\x89\xfb\x7b\xd6\xc7\xca\x69\x11\xde\x54\xf2\x9b\xb1\x29\xff\x8a\x33\x0f\x2e\xfd\xe1\x30\x5a\x56\x0c\x05\x70\x36\x50\x0f\xcd\x45\x8e\x48\xf4\xa2\xbc\x94\x28\xd0\x97\x5c\x01\x90\x38\x91\x73\x67\x02\x5d\x79\xea\x7c\xb8\x5d\x5e\x97\x8b\xe3\x63\xfe\x3b\xc8\xe1\x00\xa3\x6f\x07\x60\xb0\xe0\x9f\xff\x59\xfe\x0a\x3c\xf7\xe5\x0f\xfb\x8a\x4c\xcb\xf0\xe8\x28\xed\x47\xb3\x36\x7f\x86\x26\x28\x49\xf0\x07\xa4\x03\xbd\x2f\x53\x43\x32\x00\xd5\x10\x39\x8f\x83\xa7\x8b\xbc\xf8\xb5\xf7\x00\x29\xf2\xa7\x40\xbc\x9f\x04\xcf\x9e\x3e\xe0\xbf\x41\x54\x03\x90\x25\x47\xe9\x60\x96\x57\x92\x8d\xa7\xb2\xf1\x0c\xfe\xd1\xa9\x42\xf2\xad\xcc\x7c\xd9\x26\x53\x53\x14\x50\x1d\xc2\x97\xd7\xc9\xdd\x24\xaf\x26\x0b\x74\x4a\x8d\x54\xbc\x4b\x78\x9e\x66\x33\x8c\x98\x10\x65\x0b\x28\xac\xe9\x35\xc6\x58\x89\x30\x62\xa2\xfc\x9b\x56\xff\x43\x84\xa3\xc4\x92\x95\xf8\x72\x55\x2e\x6e\x6f\x50\xd3\xc9\x8f\xf2\x03\xac\x99\x2e\xcc\x0f\x2a\x8c\xaa\x86\xca\x9e\x86\xe2\x61\x70\x6c\xbd\xa3\xb3\x4d\xb4\x4e\x2e\x86\xd1\x77\x4f\x39\x4a\x5b\x6f\xb9\x5e\x34\xf9\x6a\x91\x25\x1c\x75\xec\xd9\x77\xc0\xda\x3c\xe0\x77\xcf\x82\xcb\x68\x82\x95\x83\xa7\x74\x25\x3c\x43\xb6\xe7\x81\x78\xbc\x8c\x16\xc9\xc5\x43\xf5\xea\x69\x83\xd4\x0c\xfc\xa9\x44\xad\x0a\xf6\x43\x94\xe9\x4f\x56\xdc\x5a\xfd\xf9\x86\x6b\xd1\xc3\x25\x26\x99\x85\x7d\x8d\xf1\xdd\xf8\x29\x2c\x1f\xbf\xa4\x87\xcb\x08\x0e\x4f\x4a\xaf\x9e\x2e\xd3\x15\xbf\xa1\x07\x18\x1b\x20\x81\x8b\xf3\xd6\x10\x64\xb7\xf0\xfa\xa6\x2a\xd7\xe2\x1b\xf5\xcb\x9c\x41\x76\x83\xa1\x18\xa9\x71\xc0\x55\x8b\x69\x9d\x35\x5c\x5b\xff\x82\x41\xa7\x55\xba\xe4\x4a\x2c\xf5\xe5\x2a\xf2\xf9\x32\x6a\x2a\xcf\x30\x78\x15\xdc\x05\x28\x57\x0d\x8d\x22\x5e\xe3\x23\xaa\xa0\xd7\xe4\xca\x8c\x4f\x93\x48\x8e\x11\x1e\xe9\x4b\xfc\x3b\x2b\xcb\x06\xff\xce\x33\xf4\x6f\x8c\x9a\x69\x8c\xa6\xce\xf0\x8f\x00\xac\x95\x86\xab\x15\x83\xd5\x4a\x41\xd5\x0a\x80\x6a\xc5\x30\xb5\x72\x41\x6a\xc5\x10\xb5\x52\x00\xb5\xd2\xf0\xb4\x72\xc1\x69\xc5\xd0\xb4\x62\x60\x5a\x31\x2c\xad\x3c\x57\xcf\x36\x41\x53\x5b\x6a\xf4\xc3\x61\x2a\x0f\x8a\xa0\x0d\x88\xaf\x31\x0e\xf6\xa8\x8f\x1a\x38\xe3\xb7\x92\x38\xd8\x37\x0a\x7f\x3b\x12\xa4\x68\x01\xe3\xff\x90\x5f\xa3\x79\xb4\x36\xe2\x31\x0a\x47\xd8\xa8\x46\xdb\x1b\x27\x19\x83\x56\x4d\x15\x52\x14\x7a\x06\xc8\xe1\x6c\x54\x70\x07\x44\x84\xaa\x1b\x80\x8a\xd2\xa4\x3c\xe1\xc0\x96\x22\xde\xab\x10\x5c\x22\xb5\x5d\x1e\x1f\xa7\xcf\x14\xbd\x7b\x47\x79\xe2\x0b\x19\x52\x38\x3b\x2d\x37\xa3\x32\x49\x37\xd8\x55\x4e\x69\x60\x36\xb6\x62\x94\x56\xf2\x30\x46\x4c\xce\x79\xac\xf5\x0c\x30\xe4\x1c\x4d\x5e\x04\x52\x33\x4c\xfe\xd4\xda\x9a\x98\xf3\x47\xdf\x55\x70\x50\x72\x6f\xa1\x4e\x29\x31\x5f\xaa\x42\xaa\x70\xab\xc1\x8d\x63\x2c\x13\xf2\x2e\x0a\xd1\x3a\x83\x1b\x5b\x15\xe3\x80\x6e\x09\x54\xec\x20\xf6\xde\x0b\xc3\x93\xab\xc1\xde\x40\x4c\x73\x3c\x4c\xd7\x21\x17\x1a\x56\x97\x89\x84\xf1\xdd\x57\xe9\x3b\x47\x76\x91\x1c\x5e\xd5\x60\x19\x9d\x39\x0a\xe7\x73\xa4\x63\xa3\x5b\xf3\xcb\xbf\xec\xf9\x25\xda\x44\xc6\xd0\xa9\xd3\x92\xf9\xda\x47\x93\xec\xd4\x2a\x78\x14\xa1\xc1\xe9\x7f\x1f\x06\x7d\x47\x9f\x20\xd4\x9e\xe1\xc5\xf3\xd3\xff\x79\xe9\xd7\x7c\xfe\x70\x18\x33\xa9\x35\x9f\x7d\x53\xf5\x79\x4a\xba\x4f\x73\xdb\xe7\xb7\xab\x79\x56\xb0\x75\x24\xea\x3e\xfd\xaa\x4f\x5d\x0b\xd0\x12\x91\xc9\x3f\x1c\x46\x26\x77\xd2\x5d\x80\xaa\x82\x75\x01\x38\x19\x70\xea\xd4\x94\xb1\x29\xef\x10\xa8\xe0\xf9\xcc\xf0\x1e\xb1\xd3\x6a\xee\xac\xee\x66\x19\xf6\x6b\x73\x90\x7a\x17\x42\xa5\x04\x69\x59\x72\x7b\xc3\xd0\xa2\xe8\xfc\x43\x9e\x1d\x2a\xad\x72\x5b\xcf\x29\x1d\xf6\x9b\x11\xf0\x04\x88\x34\x06\x62\x22\xae\x5c\x9d\x5f\x8c\x6b\x41\x1e\xc9\xdc\x45\x3a\x47\x68\xde\x8f\x01\xa3\x31\x2b\x3f\x2e\xb2\x2f\xe2\x0b\x2c\xc7\x5f\x0b\x52\x0b\xb5\x9a\x45\x7d\xa7\xd0\x96\x1a\x09\x7f\x8b\x44\xf7\xc3\xc2\xbf\xd7\x25\xa1\x02\x14\x7d\x4e\x50\x8a\xa9\xe3\xf6\x2a\x8f\x1c\xd2\x39\x8a\x54\x38\x9c\x98\xf6\x4c\xff\x5e\xc2\x19\x63\xc7\xa2\xa2\x95\x57\x8e\xe6\x50\x03\x55\x6c\x26\x06\x35\x13\xcc\xbd\xc2\x45\x34\x5f\x9a\x71\x7b\x7f\x21\x3e\xca\x7c\xbb\x3d\x61\xa4\x49\x81\x2e\x5a\x11\x21\x0d\xd9\xfc\xa6\x3f\x5a\x87\x0b\xc3\x63\xae\x94\x49\x41\xae\x3a\xf3\x7b\xc6\xf9\xa6\x1f\xb5\x64\x80\x5b\x92\x44\xb5\xa7\x1e\xff\xa8\x25\xac\xce\xc4\x63\x60\x96\xa3\xae\x79\xc7\xc3\xf3\xef\xf7\xcb\x04\xf5\xc3\x7e\x9a\x02\xc7\x36\xaf\x92\xa6\x72\x74\x01\x1f\x09\xc8\x5d\x23\xf4\x33\x37\x44\x16\xb9\xeb\x04\x81\x8d\xc2\x45\x84\xc1\x9b\xbc\x20\x59\x47\x2f\xfb\x3a\xc9\x56\x7c\xe1\x4f\xc8\xb4\x67\x3a\xea\xad\xc9\x6e\x2e\xeb\x15\x65\x71\xba\x94\x15\xa7\xd9\xe7\x5e\xa6\xaf\x89\x1e\x10\x06\x54\x69\x06\x90\xd3\xa3\x88\x2a\xbd\x25\x26\x2d\xba\xc9\x7a\x69\x31\xed\xa5\xd3\x29\x19\x2d\xa4\x8b\xde\x3c\x5b\xac\xa0\x56\x4f\x4c\xb6\x1e\xa0\x5a\x18\x20\x9e\x46\x09\x64\xb7\x31\x01\xa4\xb5\xcf\x46\xd6\x48\x7f\x92\x8b\xd6\xfb\xb7\xbc\x5c\xb0\xfb\x4c\x2f\x38\xc9\x14\x46\x7c\xf0\x4f\xf5\x83\x1b\x13\x3a\x04\xfc\x4f\x2e\x16\x27\x27\x97\x1b\x20\x23\x9a\x79\x55\x7e\xe9\xad\x07\xb3\x0a\x43\xed\x7c\x2c\xdf\x95\xab\x64\x18\xad\xbd\x56\x4b\x3f\x1e\xe6\xc2\xc5\x2b\x6e\x28\x31\xef\xef\x33\xb2\x7d\x80\xf9\x93\x00\x41\x66\xad\x34\xaf\x77\x19\x64\x43\xe4\x32\x29\x92\x00\xd0\xdc\x49\x13\x55\x49\xd1\x33\xaa\x51\x94\x90\x4a\x26\x6e\xdf\xca\x84\x8d\xd2\x01\x5c\x91\x2a\xef\x40\x58\x60\x5a\x37\xec\x62\x84\xa1\x54\x7d\x6c\x30\xda\xc9\x09\xf1\xe0\x51\x05\x94\x09\xe0\x35\x32\xe4\x25\xa6\x13\x65\xf4\xba\xc3\x7c\xb9\xe2\xce\x68\xf1\x91\x71\x7d\x0d\x23\xa0\x3c\x2a\x1c\xeb\x84\x4d\x80\x81\x0f\x78\x38\x38\x43\x5d\x08\x4b\x33\xf2\x68\xab\x0e\x79\x54\x5a\xc4\x50\xde\xd5\xdf\xf1\xf1\xee\x81\xec\x53\x27\x0c\x60\x80\x41\xff\x08\xae\x80\x33\x8f\xd9\xf1\x36\x52\xe8\xc7\x3d\x39\xff\x23\x38\x7b\xf7\xf7\x47\xbe\xd4\x2d\x48\x5c\x8f\x9b\x5e\x2e\x70\xb6\x28\x89\xdb\xb7\x8e\x36\x91\x49\x7c\x26\x32\xed\x5b\x82\x5e\xa2\xb1\x40\xdf\x55\x1f\xd1\xd0\xbf\xc9\xd6\x8a\x0c\x7f\x7e\xfa\xe5\xdd\xa7\x8f\x2c\x20\x96\x5d\x00\x9c\x5c\xb0\xb8\x18\x45\xc4\x1f\x5f\xfd\xfb\xc7\xe7\xef\x5f\x3d\xb7\xeb\x48\xc2\xe4\x8e\xd2\x2d\x90\x08\x20\xa5\xb8\x6e\xf4\x17\xbd\xa4\xf1\x39\x90\x3f\x4e\xc9\x8b\x2d\x20\x11\xc1\x12\x6d\xfc\xe1\x61\x09\x84\x2e\x89\x00\x78\x25\x58\x28\x50\xd7\x5f\xca\x6a\xca\x12\x00\x8c\xb5\x8d\x0c\x3f\xb0\x79\x93\x39\xb3\xfc\x0b\x83\xf3\x8f\x64\x2f\xeb\x8a\x8a\xbf\x64\x19\x45\x8d\xf5\x1d\xf7\x1d\xd6\x5f\x16\x11\x76\x7c\xfc\x50\xce\x14\x77\xc3\xb6\xc2\xea\xb6\xc0\x52\xaa\x36\xea\x70\x3f\x75\x8f\xc7\x84\xbd\xe5\x3e\x15\x15\xa4\x19\x0b\x2d\xb0\xe2\x0b\x0d\x50\x90\xab\x20\x62\x0b\x11\xe9\x81\xec\x8a\x9f\x28\xe0\x7a\x81\x4e\xc9\x86\xfd\xa4\x2b\x4e\xf4\xb2\xb6\x3f\x7a\xf8\x04\xf7\x96\x12\x03\x36\x47\x40\xdc\x69\x6b\x10\xda\xda\xd3\x50\x01\x7b\xf7\xed\x1b\xbc\x32\xe8\x6a\x74\x63\x2e\x91\xda\x5d\x65\xd2\x13\x63\x13\x06\xc1\x51\xd9\x27\x6d\x65\x79\x99\x68\x5d\x1a\x66\xd0\x2b\x23\x5c\x4f\x4b\x76\x9b\x4b\x2f\x6a\x4d\xa3\xda\xb3\xf3\x4d\xe2\x30\x76\xc0\x55\x86\xaa\x4f\x0b\xc3\x18\xb3\xa5\x7a\xbd\xbf\x0f\xd1\x5a\x5a\x1a\xd6\xb3\x90\x1b\xad\x3f\xf0\x02\xf0\x61\x8c\x6f\xe1\x09\x7a\x65\x88\xa6\x22\xff\x96\x2e\xf2\xa9\xbc\x99\x60\x89\xa2\xa6\x65\x40\xa6\x8d\xc5\xda\x62\xc7\x0e\x63\xb1\xdd\xa6\x61\x3f\xee\x45\x36\x45\x5b\x99\xe4\x91\xcd\x9c\x57\x32\x13\x89\xf0\x87\xc0\xe3\x25\xe5\xdf\x83\x25\x86\x09\x68\x95\x7e\xc9\xae\x7f\xcd\x1b\xe3\x8d\x75\xcd\xdc\xdf\xdf\x6d\x76\x5e\x35\xe7\x67\x1e\xf2\xc3\xc0\x08\xc6\x60\x60\xc4\x70\x6f\x57\x18\x67\x02\xb6\xb8\x4a\x30\xe8\x84\xb2\x5a\xc3\xd2\xc1\x35\x0c\x0b\xf3\x15\xb4\x0e\xb1\xd9\x0a\xe0\xa5\x1f\xa9\xe3\x6f\xb1\xd0\xf8\x2e\xf8\xee\x04\x11\xe3\x09\x3c\x98\x3b\x9d\x91\x46\xeb\xa3\x96\x59\x00\x8f\xf2\x47\xa0\xc1\x6a\xb4\xa1\x68\xef\xf2\xb6\xea\xf1\xf0\xfb\x33\x1a\xdf\x01\x59\xb8\x3a\xa4\x20\xc0\x9c\xff\xaf\x8b\xde\x5f\xab\xbf\x16\x7f\x6d\xfe\x3a\xbb\x7c\x80\xac\xf2\xd3\xf0\xe8\xf4\xf4\x1e\x25\xec\xf7\x45\xc9\xc6\x76\xf7\xa8\x5e\xb9\x17\xcf\x75\x73\xbb\xc8\xfa\xfa\xab\xbf\x3e\x78\x06\x1f\xa6\x4e\x34\x85\xc6\x90\xdb\x67\x94\xe1\xc6\xc7\x0e\xbf\xf9\xf0\x7c\xb5\x3a\x3e\xa6\x3f\x14\x75\xee\x53\x51\xa7\xb3\xec\x67\xbc\x00\x5f\x8b\xf6\x00\xf2\xdc\xc6\xb7\xd6\x0f\x4d\xff\x25\x6b\x14\x7d\x0a\x08\xa1\x40\x9a\xc1\xa8\xde\x41\x46\xd6\xa6\x02\xa2\x87\x04\x13\xdc\xed\x46\xa1\x67\x78\x84\xc8\xb5\x04\x11\x85\x96\xfa\x97\x24\xd2\xd9\xda\xb0\xe1\xac\x7e\x4d\x56\x37\x9c\xfe\xe3\x29\xd9\xbd\x5d\x9c\x5d\x1e\x1f\x97\xb2\xd8\x9e\x47\xf0\xd7\xf5\x2c\x9b\xcd\x80\xde\x17\xa4\xb2\x25\x02\x1d\x92\xf8\x71\xaa\x7d\x2d\xc6\x8d\x6d\xde\x88\x39\xbd\xa7\xa4\xd7\x44\x87\x8c\xf0\x2c\x1a\xf6\x85\x5b\x90\xb3\x56\x1a\x26\xd3\x3d\x0e\xe9\x2e\x19\xe4\x3e\xb0\xb8\xfb\xa0\x48\x0c\x49\x66\xd4\x62\xb0\xc4\x7e\xbb\xc0\x67\x08\x07\x11\xfc\x2a\x0b\x91\xed\x2b\x63\x44\xf5\x93\xd3\x32\x05\xde\xa0\x4c\xe0\x7d\x13\x95\xed\x58\xa1\x68\x8f\x13\x1d\xb9\xd3\x02\x06\xf8\x9c\x96\xf6\x30\xf7\x62\x06\x3f\xc3\xe1\x54\x44\xc2\x29\xe8\x4a\x2f\xba\x49\x8d\x02\x6f\xf6\x23\xef\x75\xd9\xc0\xc5\x88\x56\x19\xf0\xc7\x60\xd4\x54\x7b\x19\xb6\xe7\xf9\x10\x48\x2e\x4f\x2f\xba\x01\x39\xbe\xf6\x95\x7b\x7e\x76\x98\xd7\xaf\x32\x95\x3a\x42\x4e\x4d\x3a\xcc\xc8\x90\x2e\x82\x2d\x00\xae\x4f\x2a\x45\x09\x1f\x29\xbe\x21\x29\x4c\xb9\x52\xa2\x0c\x4e\x75\x85\xca\xaa\x50\xd1\xe7\x8a\x4f\x49\x2a\x3c\xe1\x0d\xcb\xd1\x33\x21\x12\x23\xcb\x11\xfa\xad\x4c\x5f\x00\xc0\x07\x57\xe4\xf3\x4b\xe5\xfc\x28\x29\x97\x5c\x3a\xd9\x1d\x0d\x37\xb6\x94\xa7\x7d\x39\x38\x22\x92\xf3\xb3\xbd\xcd\xc0\x85\xf7\x0c\xb9\x15\xb5\xc8\xe1\x43\x5c\x1b\xe0\xb8\x86\x2d\xae\x2c\xc3\x52\x61\x8a\x9b\x9d\x0e\x19\xd4\x22\x17\x04\xfa\x86\x11\x15\x0f\x41\xd3\x87\xe4\x94\x20\xa8\x32\x69\x24\x06\x93\xd9\x48\x6a\x54\x78\x36\xa1\xb5\x77\x49\xb9\xa6\x4b\xca\xed\x4c\xf4\x28\x92\xa1\x2e\x01\xfa\x0d\x8e\x4a\xe7\x67\xdf\x24\x91\x5e\xba\xe6\xa5\xb6\x93\x8c\x80\x4d\x04\x86\x71\x2a\xec\xa1\x62\xf4\x13\x62\x2b\xa5\xf0\xe1\x13\x3b\xe9\x77\x87\x71\xea\x0d\x1a\xa7\xaa\x7a\xa9\x21\x81\xfe\xef\xc1\x09\x7e\x66\x25\xf4\x16\x92\xb0\x52\x08\xbf\xd4\xee\x91\x0c\xd8\xb8\x8e\x61\xc7\xd6\x96\x19\x76\xb2\x66\x89\x30\xdb\x04\x6b\x69\xb1\x71\x22\xd6\xd6\x89\x80\x5f\x13\x0f\xb1\xab\x5c\x50\x80\x3b\xe0\x8b\x33\x1b\x4f\x91\x3c\x8a\xce\x60\xf6\xb0\xb0\x11\x8b\x7b\x56\xd1\x32\xba\x89\x6e\x61\x47\x61\x64\x2d\x2e\x4d\x6e\xfe\x15\xbc\xbf\xd2\x2e\x60\x57\xb0\xf1\x2b\xd8\xf5\xab\xcb\x68\x99\xc0\x3a\x1d\x91\xc5\xda\xc9\xe7\x78\xda\x87\x2e\x56\xd1\x15\xa6\xd4\x29\x4e\x6e\xa3\xdb\x93\xa4\x0e\xb9\x0b\x5c\x0c\x2d\x68\xbb\x4e\x66\xc2\x61\xff\x9a\x97\xe8\x55\xf4\x35\xb9\x96\xe0\x47\xe5\x47\xc8\xdd\xc2\x6c\xaa\x3c\xab\xd5\x40\xbe\xc0\x40\x8e\xc2\x57\xc9\x57\x52\x1b\x86\xfd\x3e\x5c\x1c\x45\x36\x82\xd1\xbc\x1a\x7c\x46\xc7\x41\xff\x80\xbe\xc0\x80\xb7\x0c\xa9\x47\x6a\x4a\x5f\xbb\x34\xb6\x17\xb2\xf1\xd1\x0b\xd8\x9b\x55\xf2\xe2\x62\xe8\x99\x78\x1a\xbe\x00\xda\xa1\x7f\xf2\x99\x7a\x3c\xeb\xe8\x0f\xd5\x88\xd8\xa3\x8d\xc6\xd6\xfd\xbb\x79\x38\x3c\x32\xf9\x79\x99\xef\x77\x31\x10\x91\x7c\x71\x5d\xe4\x32\x7c\xc0\x03\xfe\xbe\xff\xde\x45\xf1\x1f\xfa\x34\xc0\xf7\x17\x1f\xbc\x03\xfc\xb0\xc7\xe8\x64\x82\x31\x2b\x01\xbb\x95\xd4\x59\x1a\x42\x9f\xa1\x15\x34\xc0\x56\x74\xa6\xa3\x0a\x4c\xbc\xcc\xd5\xc2\x28\x7d\x5d\xa5\x37\x76\xaa\x3b\xcb\x78\xf8\x4f\x69\x31\x5d\x64\xb5\xce\x0a\x75\x03\x17\xb3\xb0\x83\x79\x5d\xe8\x7c\x50\xa6\x34\x62\xda\x92\xce\xaf\x06\x1f\x5e\xbd\x7b\xfe\xfe\xf9\xc7\xb7\xef\x31\x15\x54\x10\x07\xb0\x1c\x77\x01\x3e\x24\x67\x40\x48\x0e\xf0\x61\x08\x0f\x31\x3e\x9c\x07\x1b\x58\x8e\x07\x17\xc9\x20\xb6\x0d\xc6\xd7\x5b\xf8\x3e\x7b\x32\x50\xfa\x7d\xcb\x10\x5a\xce\x25\x1e\x9e\x9f\x45\xad\xa9\x00\xd2\x3b\xdb\x4b\x0e\x0f\xff\xee\x4f\xe1\xb9\x21\x0a\x81\xfd\x6a\xb3\x5c\xed\x30\x62\xd4\x8d\x87\x6f\xd5\x9f\x52\xeb\x8b\xfc\x9a\xa7\x18\xf4\xb9\x25\x5d\x10\xff\x40\x24\xd3\xd0\xc3\x32\x3a\x8d\xd4\xd5\x44\x7e\x8e\x8f\xf1\xf9\x39\xd1\xb1\xc3\xc3\xa3\x7e\x91\x9f\xd8\xac\x90\x11\x31\x45\x14\x79\x19\x0a\xb3\x84\x2d\x40\xfa\xc2\x36\x73\x23\x27\x0e\x7d\xed\x5d\x51\x38\xc1\x3a\x61\xd5\x44\x64\xbe\x5a\x08\x61\x79\x6d\xc9\x8e\x48\x70\x43\xde\xfa\xfc\x25\xb4\x6f\xfe\x84\xbb\x48\xe0\xde\x0b\x0a\xac\xed\xbc\x83\xd1\xca\xd7\xed\x37\x97\x86\x23\xfa\x59\xc4\x01\xf1\xcc\x1a\xc2\x74\xa1\x22\x85\x04\xe3\xe8\xa2\x3f\x2a\x9e\x65\xa3\x8c\x6e\xe2\xec\xd2\xfd\x04\x8a\xa0\x5d\x7d\x35\x5b\xf3\xcb\x96\x79\xe3\x55\xde\x1c\x30\x49\xa1\x34\xa0\xc0\x08\x6e\xe7\xd1\x24\x49\x85\x73\x4a\x6d\x90\x3f\x1e\xa2\x66\x8d\xcb\x22\x13\x34\xae\x69\xe3\x80\x8c\xe3\xfc\xef\xc8\x3f\x49\xb5\x05\x0c\x12\xab\x46\x28\x33\x9f\x88\xa8\xe4\x43\x99\xc5\x10\xdf\xf0\x05\xb2\x96\x90\xd0\x87\x9a\x1c\xf1\xf9\x7c\x4b\x2d\xb4\xe0\x97\xf5\x1e\x6e\xad\x87\xd7\xa6\xac\xf9\x68\x47\x4d\x20\x17\x54\xdd\xc7\x3b\xeb\x46\xb9\xae\xfd\x64\x8f\xda\x18\xac\x04\xa8\x77\x84\x97\x3a\x19\x02\x17\xa6\x41\x62\x72\x3a\xec\x8f\x26\xcf\xea\x51\x0d\x40\x91\x5e\xd4\xa7\xc3\x4b\xbd\x0f\x17\xf5\xe5\x88\x9a\x65\x0f\x74\xdd\x6e\xca\xac\x28\xdd\x77\x0b\xc0\xcc\x6b\xb9\x63\xdc\xc5\xd9\x68\x25\x5a\x94\xbb\x04\x2d\x6d\xdf\x28\xac\xd0\xda\x2b\x51\x2a\x66\x85\x3f\xe4\x56\x89\xf8\xdc\xff\xf0\x0f\x62\xbf\x3a\x6b\xc2\x76\x99\xb1\xbc\x1f\x6e\xab\x89\xa1\xf3\xb9\xae\x88\xeb\x83\xf1\xdd\x8f\x52\x22\x27\x16\xfe\x75\x5b\x8c\x16\xb4\x6e\x0b\x7b\xdd\x16\xb0\x6e\xa2\x1f\xb1\x74\x66\x47\xa9\xba\x38\xd1\xd2\xcf\x3c\x64\x65\xd1\x72\x96\x60\xfa\x18\x3b\xae\xd0\x3b\x02\x78\x3c\x0c\x8c\xa1\x2c\xa8\xac\x63\x67\xe1\x8f\xe4\x6e\x23\x02\xbc\xe8\x43\x36\x6e\xa3\x11\xb7\x28\x71\x51\x4d\x94\x5f\xc6\xee\x67\x14\x7e\x20\xef\xbb\xe5\x49\x1e\x49\x9f\x33\x73\x4e\x80\x58\xf7\x9a\x15\xee\xfe\xff\x87\x26\x66\x03\x71\x6b\x8a\x7b\x63\x45\x9a\xab\x19\x7c\xd9\x1c\x62\xc2\x17\x03\xb9\x1e\xc1\xa4\xc4\x9f\x23\x62\xdd\xe0\xd7\x51\x45\xeb\xdb\x47\xfb\x2c\x1a\x3b\xe2\x11\xac\xa1\xa9\x71\x36\x7b\xab\xe4\x09\x4d\x05\x2b\x46\xba\x01\xbb\x29\x2c\x70\x5a\x33\x6c\x96\x7b\xb9\x12\x54\x39\x8b\x33\x24\x0b\x13\xf1\x32\x07\xb2\x36\xce\x63\x96\x5c\xf5\xdc\xf9\x74\xad\xe2\xf3\xc5\xe2\x67\xef\x05\xea\x01\x87\x71\xd8\x8c\xfd\xcd\xc7\x0e\x98\x44\x1c\x44\xc6\x03\x93\xb3\x59\xd2\xbd\x95\x56\xd5\x74\x3a\x55\x5b\x6c\x83\xb5\x55\xad\x46\x1f\xdc\xaf\x9e\x39\xb4\xbc\x31\x49\xef\xfc\x0a\x6e\xd3\x06\x5b\x74\x0a\xce\x5b\x25\x0f\xa1\xa4\x65\x19\x7f\x3e\xf4\x88\x94\x43\x73\xdd\x8e\x8c\xb7\x94\xc1\xa3\xc0\x9d\xc2\x7f\xee\xef\xab\xb0\x1f\xf9\x84\xbc\x14\x07\x4d\xf4\x34\xd6\x7d\xe2\x47\xb1\xe7\x1e\xe6\xef\x8f\x8f\xf9\xef\x20\x5d\x4e\xe5\x73\xd8\x9e\x3d\x36\xb2\xe9\x6f\xc2\x00\xb8\x8f\x65\x8e\xce\x24\x5e\xab\xab\x71\x43\xbb\x65\x9a\x44\xf8\xa9\xba\x46\x98\x78\xe2\xfe\x70\x68\x94\x15\xa0\x89\x55\x32\x0d\x67\x98\x47\x27\x47\x13\x4c\x55\x39\xb3\x3c\xb0\x24\x73\x6d\x33\x28\xc0\x26\x0b\x0e\xeb\x08\x7d\xad\x4c\xb7\xcb\x02\xf5\x50\xe8\x57\x30\xcf\xe0\x4a\xef\xb0\xdd\x37\xe9\x46\x1c\xb6\x3c\x7e\x0d\xdc\x86\xcd\x53\xa6\x38\xe7\x30\x2e\x79\x0e\x1b\x24\xc2\x58\xa5\x85\xe7\x87\x2a\xd4\xe8\x86\x31\xd6\x75\x11\x23\xd5\xeb\xc9\x04\xf3\x9c\xd8\xa5\xb3\x34\x5f\xac\x2b\x41\xba\xca\xd2\xfe\xa8\xd5\x4d\x72\xb6\xb1\x08\x61\x9d\xcc\x25\x2a\x29\xd4\x50\x41\x76\x65\xe3\x0a\x8e\x00\x4e\x3e\x6c\x06\xcb\xfa\xa6\x1f\x87\x80\x9c\xf1\xcd\xd9\x98\x0a\x62\x71\x5f\x0a\xba\x97\x2b\x01\x72\xc2\xd4\x27\x2b\xde\x50\xdd\x04\xf2\xa3\xc2\x00\x46\x6c\xf6\x29\x0d\xa9\x37\xb9\x9d\x2c\xb2\xa0\x0f\xad\x97\x09\x5a\x90\xa1\x23\x2c\x35\x9b\x47\xf8\x71\x5d\x2e\x3e\x67\x91\x6c\xa6\x1f\xab\x32\xac\x2a\x64\x4c\x29\x86\xf7\x11\xfd\xe0\x35\x6a\x90\xea\xd2\xda\x24\x5a\xa3\x4d\x16\xa2\x54\xc4\xc0\x13\x74\x19\xbf\xb9\xc9\xaa\x6c\x0a\x64\x85\xfe\x41\xc1\xbc\x30\x7e\x1f\x60\xd4\x49\x42\x4f\x7d\x5a\x90\x30\x85\xb1\x55\x30\xb6\x90\x4d\x79\xea\x70\xd2\x8f\x52\x1e\x67\x65\xc2\x65\x2e\xaf\xf6\x48\xdd\xfb\xc0\xa7\x18\x15\x4a\x5f\x05\x9c\xfd\x04\x97\x2f\xa9\xa0\x7f\xda\x70\xa0\x2c\x26\xd6\xa6\x3d\x3b\x03\x32\x29\x2c\x80\x10\x92\xd3\x5e\x60\x6b\x4c\xb1\x00\xae\x96\xa3\x5a\x60\x06\x2d\x43\x18\x95\x29\x7d\x1b\xce\xbe\xd2\x93\x45\x25\x9b\x3d\xf5\x4a\x4c\xbd\x4a\xe8\x09\xd5\x2d\x38\x26\x5c\x7e\x1e\xd3\x39\x2a\x60\x3c\x63\xaa\xfa\xb6\x5c\x4b\x26\x08\x52\xa9\x01\x50\x36\xa4\x23\x5f\xe5\x00\xe5\x1a\x15\xe5\x28\xf1\x97\x9b\x9a\x5d\xe4\x97\x7d\x3a\x53\x16\xe2\x82\x5a\xe8\xf4\x89\xf2\x33\xa8\x6f\x89\xc9\x74\x08\x79\xc9\xc3\x19\x73\x1a\x5a\x22\x08\x51\x55\xc0\xa6\xac\xce\x53\x3b\x6b\x7f\x6b\x9c\x23\x15\xcb\x0e\xd7\x43\x38\xe4\xa8\x96\x27\x21\x4b\xb0\x3d\x4e\xd9\x59\x9f\x4d\xb5\x0c\xe8\xff\xa5\x6c\x7a\xa9\x52\x75\x07\x24\xa8\x3a\x3b\x12\x67\xfd\xea\xea\x97\x77\x6f\xaf\xae\xba\xbe\x12\x23\x0f\xc4\x99\x16\xb5\x93\xa1\xa0\x13\x10\x06\xd6\x1c\x23\x8d\x2b\xe0\x3a\xea\x4b\x27\x03\x0e\x41\x38\x19\xdf\x49\x04\xd2\x85\xb7\xce\x22\x81\x4c\x7c\x35\xf2\x71\x8e\x98\x4d\x67\xae\x91\x2b\x8a\x03\x70\xa3\xc6\x87\xe6\x8d\xd4\xb5\x4e\x8d\xd7\xa5\x7d\x9f\xd5\x2b\x25\xe8\xc0\x76\x96\x02\x09\xa0\x02\x4c\x41\x2a\x91\x2c\xc0\xea\xe0\x1a\x0b\x38\x96\x40\x1b\xa9\x91\x33\x51\x70\x11\xd0\xc1\x0a\x2e\x3b\x89\x0d\x02\x4c\x89\xef\xfa\x1b\xc2\x0d\x99\x85\x05\x2d\x3e\x5f\x22\x88\xc6\xc4\x01\x8d\x3a\xb6\xf4\xc2\x40\x62\xaa\x18\x91\x98\xe0\xa2\xa2\x59\x34\x6f\x5b\x62\x48\xc9\x73\x34\x4d\x7c\x37\x26\x6a\xa2\x96\xcb\x6c\x8a\x46\xa3\x63\xcf\x5c\xcc\xf7\x28\x76\x8e\xa1\xe0\x63\xbe\xcc\xca\x75\x43\x53\x12\xfd\x71\xbb\x4a\x32\x08\xa4\x53\xf0\x35\x88\x90\xd0\x5e\xb4\x98\x7e\xd5\xb6\xff\x5b\xac\x75\x47\x02\xd0\xb8\x88\xbe\x54\x39\xb9\xd5\x90\x6b\x15\x25\x08\x58\x57\xf4\xbb\x42\x63\xb6\x21\xe6\x00\xe4\x35\xf9\xdc\xbf\x73\x7b\xd2\xfb\x41\x09\x07\x22\x0c\xaf\x61\xd2\x55\x2e\x2d\xe0\xc8\x77\xea\x6c\x31\x53\x79\x4e\x50\xd0\x63\x78\xd7\xd1\x3c\x04\x50\xdf\x01\x05\xa1\xe3\x0a\x91\x40\x83\xcf\x57\x43\x3f\x22\x8c\xf3\x4a\xdf\x57\x31\xa6\x0d\x28\xe0\xbf\x4a\xb6\x15\x11\xa9\xd1\xce\xa7\x20\xcc\x85\xe0\x0e\x5d\x89\xaa\xe8\xd6\xd2\x28\xbe\xb3\xa1\xd1\x01\x17\x93\xb0\x47\x0b\xe0\xf1\x90\x45\xb8\xcb\x64\x41\xab\x6f\x1c\xab\x20\x9a\x44\x86\x6d\xf4\x22\x9c\x44\x81\x82\x8f\x20\x5a\xe2\xcb\x68\x11\x2e\xa3\x40\x60\x09\x94\xb1\x72\xd9\x04\x6d\x29\xe9\xcc\x04\x16\x54\x6a\xa7\xd1\x91\x56\x7d\xf8\x0c\xfa\x88\x34\x91\xd8\x07\x88\x33\x5c\x17\x83\xbc\x93\x8c\x8e\xef\x44\x7b\xcf\x79\xb1\xc7\x39\x27\x38\x45\x13\x00\x31\x7e\x1a\x54\xe4\x81\x6d\x89\x83\xfe\xce\xe3\x29\xac\xf1\xc0\xf6\xed\x58\xcb\xe0\x82\x17\x92\x25\x05\x97\xd0\xd9\x5c\xaa\x2a\xc6\x99\x87\x48\xa2\x0e\xe1\x32\xe5\x48\x5e\xfd\xf8\x8c\xd6\x5c\xb0\x53\x99\xba\x2f\x2f\x2e\xfb\xee\xf2\xd3\x61\xf4\x4f\xb7\xf0\x4e\xb7\xda\x63\xba\x52\x03\x2a\xe4\x87\xa5\xd0\xe4\xe5\x68\x1f\x7f\x36\x4a\x61\x8d\x1b\x27\x9a\x1e\xba\x0b\xc3\x49\x3b\x39\xa9\x91\x11\x3c\x3e\x2e\x00\x09\xd3\x05\xae\x37\x91\x1c\xd1\xff\xae\xab\xf6\x7f\x62\x69\x7c\x93\xc7\xd0\x76\x6a\xb2\x13\xfc\xd7\x30\x56\xf3\x61\xec\x9b\x45\x79\x9d\x2e\xc6\xfc\x27\xf6\xe3\xf4\xc5\x6c\x8c\xff\x78\xdf\x0a\x17\x25\xfe\x13\x03\x8a\x96\x2c\xa1\xc7\xb2\x43\x33\x71\x64\xc0\x45\xd5\x3c\x56\x0a\x85\xb0\xa8\x99\x7e\x00\x74\x83\x69\x29\x2f\x23\x55\xf4\x9c\x6a\x8a\x32\x4a\xbb\x69\xe1\x60\x54\x85\x39\x9f\x4b\xda\xaf\xef\x96\xaf\xca\x55\xc8\x5a\xa9\x91\xdb\x7c\xfb\x1b\xf9\x82\x3e\x52\x83\xef\x34\xd8\x24\x5d\xc1\x9a\x12\xe0\x29\x0b\x95\xff\x2c\xf3\x02\x7e\x0e\xa4\x89\xe9\xbf\xc0\xef\x17\xd8\x3a\xb9\x4c\x9b\xd0\xa8\x24\xe9\x22\x84\xe5\xdd\x66\x54\x3c\x0d\x1b\x0e\x45\x56\x65\x00\x31\x70\xfa\xe4\x18\x4f\x4e\x8a\x3e\x87\xe9\xe0\x97\x18\xcf\x15\xaf\x28\xb2\xb7\x44\xa9\x3a\xfc\x63\x58\x58\x5a\x46\x2f\x86\x25\xa4\xf2\x4e\x64\xf5\xbb\xb4\x3c\xe0\xe8\xb0\x25\x9e\xb7\x75\x92\x86\x40\xdf\x91\x09\x64\xae\xea\x4f\xb0\xfe\x9a\xeb\x2f\x92\xf5\xc5\xe4\x12\x6b\x9c\xa0\xe5\xcc\x0a\x2e\x5b\x0c\x10\x09\xcc\xc1\x65\xb2\x50\xda\xb9\xcc\xb4\x42\xbd\x9b\xa7\xb5\x14\x53\xf8\xc3\x02\xb3\xcc\x98\xe8\x78\x96\xbb\xd5\xeb\x6b\x36\x29\xc3\x0d\x71\x96\x22\x27\x39\x53\x05\xe0\x21\x43\x90\xb6\x3f\x01\x42\x5f\xa8\x47\xf0\xea\xef\x47\x19\x5a\x04\x3c\x55\x12\x29\x54\x47\xa0\x55\x48\x82\xab\x17\x15\xac\xc1\x26\xf3\x77\x39\x4e\x40\x29\xe6\x4f\xad\xb1\x3e\x3a\x93\xb6\x29\xc3\x4d\xc4\x5d\x7c\x2c\xdf\xa4\xc5\xad\x27\x61\x43\x6a\xaa\x44\x85\x39\xcc\x9d\xb4\x39\xc4\x23\x7b\x9d\x4e\x7e\xa5\xc8\x75\x05\x99\x2f\xcd\x29\x73\x19\xd0\xbf\xf4\x54\x5c\x8e\x0b\xe1\x9f\x3f\x2a\x85\x14\x5b\x76\x48\x46\xaa\x68\x58\x4b\x9f\x9c\x04\x22\xf9\x54\x70\xc9\x62\xcd\x8b\xd2\x2a\x2a\x11\x9a\x3f\xa3\x02\x1e\xc0\x9c\xa7\x04\xe4\x9d\x37\x3e\xbc\x90\x0b\x8c\x03\x39\xf3\x5e\x5e\xf7\x0a\xc4\x4a\xb0\x8e\xbd\xa6\xec\xf1\x08\xf0\x29\x6f\x10\x61\x04\xc0\x34\xe7\xb5\x32\xb0\x6b\xc4\x10\x31\xc2\x8e\xb5\x9c\x8d\xbd\x9c\xc8\x46\x18\x9d\x4c\xd2\x02\x3b\xd1\x8d\x63\x85\x9e\xde\xc1\xde\x75\x36\xc1\x80\x20\x3d\xc0\x46\xe8\xe0\xbc\x5e\x20\x28\x96\xe5\x2a\x10\x2b\x14\x37\x27\x01\x0e\x15\xe8\xed\x1a\xe6\x06\x48\x54\xb4\xb5\xcc\x9a\x79\x89\x41\x4a\xe4\xd2\x79\x33\xdb\x0a\x87\x9a\xa4\x0d\x49\x9e\x22\x84\x47\x75\xd8\x06\x84\xc3\x7f\x12\x8a\xb4\xd6\x22\xb3\x5d\x2f\x91\x89\x19\x10\x9d\x3f\x71\x60\x68\x11\xfc\x02\xd5\x35\x74\xef\x51\x6d\x6a\xe1\x02\x7d\x05\x98\x84\xec\x9b\x18\x43\x92\x79\x68\x5d\x38\xcd\xbe\xbe\x9d\x01\x49\x3f\xd2\x9d\x9f\x12\xd5\x14\x05\x1f\x2b\x74\x3e\x82\xf5\x63\xf1\xa2\x5c\x84\x74\x01\x38\x68\x7a\xdb\xbb\x29\x8b\xac\x87\x51\x6f\x7a\xd6\x84\xa8\xda\x11\xc5\x59\xa8\x57\x14\xfb\xb3\x89\x30\x44\x1c\x66\x64\x4b\x81\x9d\x43\xe7\xee\x32\xd2\xbb\x11\x37\x1b\xa8\x4a\xbc\x4f\xda\x8f\x52\xce\x6b\xa6\xa6\x6c\x2d\xb1\x8b\xe8\xf2\xae\xf5\x2c\x9e\xe6\x66\xec\x6a\x14\x40\x27\x39\x02\x79\x66\x1c\xe4\xc4\x0c\x71\x4c\x79\xd0\x42\xe4\xc5\xf4\x2a\x1c\xa1\x58\x58\xae\x10\x9c\xfb\xe0\x35\x30\x9a\xbe\x15\xd9\xb2\x08\xd6\x09\x77\x66\x66\x85\xec\x36\x24\x6e\x51\xd6\x35\x2f\xa0\xcc\xd5\x4d\x83\xb6\x9b\xed\x51\xcb\xf7\xc8\xa6\x9f\x0e\xbf\x65\xc8\xc0\xff\xb9\xc0\x15\xdb\x24\x43\x96\x08\x3d\x18\xc3\x97\xb4\x0e\x15\x22\x2b\xeb\x04\xa3\x2c\xde\x39\xd2\x68\x17\x60\xb4\xdd\xd7\x36\x6b\xce\x9b\x90\x42\x97\x59\x5f\xe7\x2c\xc3\x1c\xe7\x8e\xdc\x05\x29\x05\x16\x56\x15\x96\xb0\x2a\x36\xe3\x8b\xe7\x88\xb8\xf0\x4e\xfd\x08\x4c\x0f\x3a\xe0\xc7\x79\x18\x60\x0c\x4e\xd8\x26\x2c\xfe\x19\xa0\x5a\x94\x92\x9d\xab\x28\x7e\x41\xd7\x02\x96\x22\xe9\xcc\x65\x1f\x48\x9c\x8b\x65\x42\xb0\xdb\x17\xf6\xe5\x7c\x65\xc7\xe7\xe7\x94\x70\x84\xef\x73\xf8\x45\xf6\x5e\x43\x8f\xf5\x5c\xf7\xe5\x2f\xb1\xd9\x1b\x42\x39\xb5\x6d\x52\x86\x56\x32\x59\x31\x0d\xef\xbc\xd1\x67\xf3\x41\x1b\xd0\x36\x38\x7d\x1a\xa2\xdb\x70\x0c\x54\x89\x67\xb0\x1e\xe3\xb4\xf6\x60\xcd\x7b\x79\x55\x65\x28\xf2\x37\x21\x1a\x20\x7e\x5e\xae\x17\x53\xb7\x5c\x2b\x0f\x19\x1a\xdb\xf0\xc5\x37\x8f\x80\x2c\x4d\x14\x03\x49\x8c\x61\x71\x78\xab\xc9\x0c\x27\x62\x69\x21\x45\x8e\xb7\x74\x6f\x19\xab\x1f\x4c\xfd\x07\x63\x55\xd2\xae\xfc\x9c\x5e\x67\x0b\xc4\x98\xa6\x40\x94\x05\x8b\xf2\x43\x47\xc7\x5b\xd9\x1f\xc2\x7e\x0b\x81\x8c\x2f\xb7\x12\x47\x33\x12\x42\x39\xa6\xb2\x14\x22\x09\x70\xcf\x50\xfb\x33\x0d\xfa\xcf\x92\x33\x71\x17\xb7\xab\xcd\xe8\xe4\x52\x1d\x92\x04\x4b\x56\x4f\xfb\x67\x7e\xf7\x6e\x7d\x0d\x0b\x38\x87\x2b\x6f\xb9\xae\x9b\xde\x3c\x85\xf3\x6d\x34\x4f\xce\xa0\xb2\x9d\x1e\xf5\xd0\x5b\xc9\x4f\xea\xef\xfa\xa3\xa6\x2d\xbe\x54\xf8\x50\x35\x13\xba\x22\x21\x55\x85\x5b\x66\xee\x52\xec\xe4\xf3\x62\xfa\xae\xb5\x2c\x76\xd2\xc3\x91\xda\x5e\x91\x5a\x01\x20\xf7\x05\x1c\x2d\xf1\x5d\x12\xfa\x4a\xef\xef\xcf\xfa\x27\x43\x53\xc9\x28\xae\x39\x73\xff\xc8\xc9\xc8\x5d\xa4\xe0\xd5\xd7\x15\xb0\x5e\x80\x03\x35\x2b\xd4\xe3\x29\xf0\xd5\x2e\xb6\xb1\x77\xbd\x6e\xe0\x4a\x6b\x7a\x68\x07\x29\x3a\x52\xa8\x84\x2e\x56\x09\x75\x95\xe1\xe6\x2d\x3e\x96\x1e\x4a\x78\xc6\xb4\x13\x97\x31\xb6\xc2\x9d\xd0\xe9\x69\x54\x89\xaf\x10\x96\x84\x30\xb7\x2d\x89\xd1\x43\x10\x97\x82\x38\x66\x32\xa8\x3e\x2d\x23\xec\x64\xa2\xbd\x8d\xc7\x0d\x51\x51\x32\x54\x2a\x06\x3e\x1f\x67\xf1\x85\x11\x63\x5f\x08\x98\xd4\xd9\xb4\x1b\x13\x10\x29\xcf\x01\xfe\x6d\x9d\x1c\x84\x09\x31\xe6\xe7\xf5\x6d\x31\xd9\x3d\x70\xa0\x2f\x50\x52\xf4\x31\x9f\xfc\x6a\xe3\x6d\xd1\x8c\x5a\x5e\x06\x27\x51\xda\x02\x26\x33\xe3\x27\xb4\xac\x7b\xf9\x1d\x8f\x5b\x44\x14\x35\xb1\x71\xa2\x7f\x3d\x62\x69\x30\xd4\xb8\x1b\x2a\x29\x09\xda\x07\xff\x5c\xa5\x17\x85\x00\x9a\x91\x7a\x32\x04\xdf\x66\x6c\x7f\x3c\x9b\x24\xc2\xd3\x15\x0b\xfd\xac\xd2\x2a\x98\xea\x9b\xc6\x59\x4e\x3c\x7b\x1b\x4e\x15\xd5\x67\x5f\xe6\x46\x9f\xec\xd6\x19\x6a\x30\x5c\x39\x10\x6e\x21\x92\x6b\xb8\x0f\x48\xc4\x8a\x63\xbe\xad\x32\x19\x04\x13\x3a\x31\x40\xc2\x4c\xfb\x00\x0c\x28\xd2\x7f\x5a\x15\xbf\x11\xf7\xa5\x73\xe9\x78\x4c\xff\x7c\x22\x80\xad\xa6\x7b\x36\xde\x71\x18\x26\x58\x08\x21\xf5\x05\x62\xc3\xb0\x25\x7d\x99\x31\x21\x54\x02\x73\xe1\x15\x0b\xcb\xdb\x6f\xc7\xd7\x74\x29\xb1\xf3\x38\x1b\xd1\xfa\x65\x35\xf2\x9d\xcf\x0b\xa2\x8f\x66\x36\x79\xb1\x06\xf8\xa0\x58\xad\xf0\x0f\xbb\x93\x35\x86\xd1\x52\xce\x89\x6c\xfc\x02\xa2\x7c\xaf\x86\x73\xd5\xaa\x0e\xff\xcc\xeb\x7b\xbe\xdd\x11\x8e\x8e\x8c\x26\x54\xda\xa4\x80\xbd\x03\x42\x4a\xed\x10\x77\x9e\x48\xf8\xf9\x76\x3a\x71\x6c\x62\xb8\x36\xad\x08\x54\x0f\x0b\xe0\x42\xe4\xc2\x2f\x3c\x35\x2e\xfb\x98\xf0\x45\x07\xec\x7f\x99\x4f\xdf\xb8\xd1\xfa\x73\x49\x59\x11\x7e\xa9\x06\x0e\xb1\xd4\x37\x68\x5d\x60\xa8\xcc\x11\xb1\xc8\xbe\x71\xe9\x65\x44\xfd\xb2\x38\x74\x86\x78\xd9\x47\xbd\x8c\xc5\x89\xa3\xdf\xeb\xc6\x9f\x53\xc0\x18\x0c\xc6\xdb\x18\xf8\x2a\xc9\x63\xc5\x5b\x84\xb6\xa6\x6d\xca\xee\xdc\x63\x79\xfa\xad\xbb\x6b\xda\x49\x27\xb9\x4d\xf8\x8f\x51\x7f\xb2\x6d\xdb\xd1\x39\x64\x17\x6b\xe0\xd6\xd1\x6e\xca\x85\x41\xd9\x7b\x36\x5b\x5e\xe1\x3b\xab\xa9\x30\x91\xf6\xe6\x54\x0c\x2d\x02\x78\x7f\x17\xb0\x61\x99\x8c\x23\x4e\xf3\x4c\xb0\xd4\x00\x23\x46\xcf\x3e\xcf\xea\xf0\xab\x59\x61\xf9\xa8\xec\x82\xaf\x0a\xe1\xab\x0d\x60\xe9\xdf\x1d\xc0\x3c\xb6\x3d\xdd\x7c\x8e\x84\x37\xe1\x70\xf7\xaf\x59\xb6\xe2\x94\x88\x92\x9f\x18\x9a\x4c\x04\x32\xd1\xd6\xfa\x35\x28\x6c\x03\x46\x03\x29\x1e\xc6\xcd\x32\xd6\xe3\x1d\xe7\xb4\xe2\xdc\x1e\x9b\xbe\x9d\x08\x3c\x1f\xb0\x7c\x56\x6e\x10\x19\x4a\x92\x0c\x34\x1f\x28\xaa\x5a\xbc\x44\x71\x68\x8b\xaa\x7c\xc1\x32\x26\xe0\x10\xaa\x2a\x9f\x66\xbd\xe7\xef\x7e\x12\xd2\x21\x0c\x90\x82\xe2\xa3\xa2\xf7\x3e\x9b\x2d\xd6\x5f\xed\x9e\x06\xbd\x4f\x35\x46\x69\x29\x1b\x22\xdb\xf9\x8b\x02\xc6\xd8\x2b\x2b\xdd\x5a\x0e\x2d\xab\xef\xdd\xf1\x50\xc8\x01\xe0\x55\x31\x96\x8b\x23\x84\xe5\x69\x14\xfe\x69\x14\x87\x4e\xa3\xe0\x69\xa4\xc2\x76\x00\x09\x22\x78\xf8\x9d\x67\xa0\xe5\xd0\x89\x2d\xaf\xc6\x34\xe5\x48\x47\xbc\xcf\xea\xf5\x02\xa3\x62\x78\x6b\x4a\xa2\xf6\xc2\xa0\xf3\x22\x49\xcc\x5d\x1a\xb9\x39\xd6\x09\x66\xbf\xbb\xdb\x8c\xd6\x4f\x8d\xaf\x85\x30\x65\x2d\x13\x9c\x2d\x4c\xb9\xf8\xfa\x72\x34\xb9\x58\x5c\x26\x75\xb8\x60\x7f\x8f\x95\xc1\x79\x6b\x62\x38\x0e\x78\x85\x82\x48\x90\xcc\xa4\xcb\xa9\x2c\x2b\x38\x4c\x22\xc8\x70\x10\xb3\xcd\xac\xbb\x24\x91\x03\x91\xe8\xae\x3b\xf3\x58\xe1\xcd\x2e\x66\x03\x5c\x95\x71\x20\x68\xad\x20\x0e\x6c\x5a\x39\xb8\x14\x94\xd7\xcc\xa4\x0c\xb5\x88\x51\x4c\x60\x16\x4d\xa2\x15\xda\x15\xb8\xfa\x0a\x14\xc4\xcd\xa0\x73\x53\xe8\x5e\xf3\xa9\xa7\xc3\x19\x9f\x0f\x45\xa4\xc5\x2d\x28\xc0\xa3\xcb\x39\x1c\x05\xd0\xaf\x65\xfe\x95\x1c\x72\xeb\x6e\x8c\x20\x22\x5b\x21\x39\xe3\x93\x96\x58\xf2\x43\x6d\x52\xa7\x2d\xea\xce\x94\xeb\x82\x2d\xac\x95\x96\x34\x62\x5b\x13\xcf\xb6\x3a\x7c\x51\x12\x70\xf6\xdb\x20\x5a\x4b\x6e\x4a\x67\x5b\x74\x25\x61\xb2\x5c\x32\x5c\xf8\x2c\x73\x5a\x6a\x29\x25\x7b\x83\x65\xae\x82\xc2\xac\xe0\xa6\xea\xb3\x30\x3e\x6a\x13\x48\xc0\xdf\xdf\x08\x5c\x69\x23\x8d\x7c\x40\xda\x2d\x13\x11\xd6\x84\x41\x42\x2f\x0a\x01\x42\xde\xbd\xdd\xc8\x59\xf7\x9b\x30\x8b\x40\x0f\xe6\x00\x7e\x0f\xec\xf2\x40\xbe\x71\x06\xea\x43\x9c\x13\x8d\x38\xeb\x8b\x49\xc7\xb4\x27\xde\x69\x4f\x0e\x9e\xf6\x84\xa7\x5d\xe3\x7c\x7f\x57\x7c\xba\xcf\x8c\x1b\xd2\x20\x45\x0a\x01\x64\x46\x0c\xb7\xd6\xe4\xfc\x18\xca\xdc\xa8\x48\x48\x49\x16\x74\x2c\x32\x6d\x61\xe5\xe8\x4c\x11\x9d\x2c\xfa\xd1\x62\xe3\x41\x21\xe6\x89\x85\xb2\x1f\xdb\x68\x85\x4f\x3f\xfc\xfa\xc1\x83\x64\xbc\x9a\x60\x0b\x8b\x32\x62\xb0\x8a\x02\x0c\xc7\xe7\xcc\xb6\x43\xe2\x0a\x15\xdd\x45\xe0\x9a\x6e\x29\x55\x35\x17\x47\x64\x1b\x36\x4a\xa8\x8a\xc8\x82\x44\xc3\xb1\xb2\x38\x09\x05\xbd\xaa\x42\x5f\x9a\x35\xa8\x80\x2b\x94\x45\x81\x86\x63\xfc\x92\x7f\x98\x2f\x5e\xe7\x0b\xc4\x55\xe6\x6b\x2e\xb2\x27\x8e\x14\x9e\x33\x6d\x2c\xa2\x4a\x12\x75\x48\x2f\x38\xfe\x65\xbd\x42\xac\x62\xbf\xc6\x92\x40\x52\xdd\x96\xfa\x1a\x0d\xd9\xf2\x89\xa1\xbc\x1e\x15\x03\x53\x0c\x0f\xd4\x6c\x4a\x99\x81\xa4\x30\x9e\x5f\x0b\x71\x3c\x96\x4b\x71\x3c\xbf\x60\xe1\x3b\x96\x4b\xe1\xbb\x78\xc1\x92\x7a\x7c\x41\x92\x7a\x69\x09\x62\xb2\x31\x85\x63\xbe\x6e\x63\x73\xd8\x6f\x21\x67\xc9\xe5\x93\xb3\x6b\xf5\x76\x5d\x78\xd5\x1d\xf5\xa0\xea\x4b\x8b\xc6\x06\x28\x73\x8a\xf2\xad\x28\xd6\xb2\x3f\xae\xe2\x72\x94\x5d\xa4\x97\x89\xdd\x1f\x5a\xa2\x28\x2d\x78\x44\xac\xa4\x35\x01\x53\x70\xe4\x11\xcf\x3b\xd3\xb5\x2f\xaf\x44\xb6\xf8\xce\x23\x85\xf2\x36\x26\x2b\x56\xea\xc9\x69\x42\xe4\xd9\x6b\xb5\x54\xb8\x2d\x59\xd2\x35\x6e\x45\x4a\xcc\x76\x7f\xac\x6a\xd2\x77\x57\x57\xbf\x02\x4e\xb1\x48\x07\x79\xc7\x1a\x66\x88\x88\x6a\xee\xef\xd1\x2a\xad\x5c\x00\x69\xc0\xc8\xba\xa3\x1e\xab\xa8\x3f\x03\x74\xe2\xfd\x3a\xe8\xbd\xfa\xf0\xb8\x57\xcf\xf3\x65\xaf\xca\xfe\xb6\xce\xab\x6c\x3a\xe8\xcd\x9b\x66\x55\xc7\x0f\x1e\xdc\xe4\xcd\x7c\x7d\x8d\xac\xd2\x83\x7a\x55\xe6\xbf\x66\x0f\x2a\x42\xc4\xff\x59\xff\x63\x56\x3f\x96\x8e\x9f\x36\x02\x02\x4c\x47\xf1\x2a\x2d\x54\xd8\xa5\x95\xb1\x4f\x27\x94\x3e\x89\x7c\x08\x08\x5e\x90\x47\xae\x85\x72\xa0\x90\xd0\xa6\xc4\x12\x80\x38\xcf\xa2\x16\x5a\x80\xd2\x61\xe4\xa2\x22\x28\x3c\x8f\x1c\xec\x03\x65\x34\x6e\x5b\xc7\xa5\xd0\x03\x14\x3c\x89\x5c\x84\x00\x85\xdf\x7b\x30\xf7\xf6\xf4\x37\xb6\x60\xc1\x11\xa0\xa2\x69\x47\x61\x13\x6a\x98\x2c\x6d\xac\x35\xb5\x4d\x3f\x3e\xe5\xa0\x21\x6b\x5b\xa5\x5d\xb6\x55\xda\x38\x97\xbd\x15\xda\x9c\x1a\x36\xb3\x52\xc3\xc2\x59\x46\x3d\xa5\x54\x75\x97\x18\xe5\xc6\x89\x0a\xde\x98\xc4\x1a\x9f\xbd\xa9\xe1\x89\xd7\x0c\x38\xbc\xc1\xdb\xd9\xcf\x06\x4d\x87\xdc\x4f\x75\x53\xef\xac\xd7\x0a\x1a\xee\x5f\x35\x0a\x5d\x8b\x22\x03\xcd\x12\x90\x5b\x96\x67\x68\x28\x97\x12\x6e\x8f\xa8\x15\xaf\x60\xff\x6f\x6e\xd9\xa5\x51\x22\xdc\xb8\x45\xf6\x30\x4e\xe6\xe5\x64\xe6\x4b\x19\x59\x48\xc7\xe2\x9e\x32\x58\xef\x35\x5f\x30\xfa\x06\x9c\x65\x6a\x94\xb0\x7e\x9c\xd1\x7c\xc9\xc9\xc7\x70\x78\x24\x4c\xae\xdf\x31\x39\x51\x88\x40\x42\x1d\xa3\x47\x35\x9e\x6e\x8d\x5a\xa0\x38\x28\x72\x2e\x63\x20\x58\xe3\x02\x8d\xe1\xcc\xad\x4a\xed\x64\xc0\x68\xe1\xe3\x5d\x71\x69\xee\x73\xe4\xdb\x56\x14\x15\x88\xe0\x9f\x8d\xb2\xc9\x91\x82\x70\xe5\x62\x2d\xf6\x56\x08\xd9\x39\x36\x94\x37\x40\x89\xe4\x6c\x24\xbf\x34\xf1\x91\x04\x0b\xb4\xa9\x20\x75\x74\xa0\x6f\xc7\x20\xa2\x3b\x93\x8b\xc4\x4d\x1a\x44\xb8\xd2\x5c\x24\xef\xde\x20\x4a\x31\x3f\x8f\xbe\x3d\x83\x0d\x20\xd8\xd6\x8d\xed\xb3\x32\x77\x20\x2c\xf3\x40\x98\x8c\x06\x1b\xde\x21\x6f\x63\x0a\xcc\xc8\x7a\x60\x01\xfb\x73\x69\xea\x9e\x32\xc9\xe2\x04\xa6\x22\x01\x73\x0d\xa3\xa1\x75\x54\xf8\x2c\xe1\x76\x0c\x4d\xa3\x00\xd7\x3b\xfb\x29\x20\x33\x41\xad\xf3\x82\xf6\x52\x86\x5f\x80\xfd\x79\x0f\xb3\x2e\xf6\x1a\x60\xe6\x7a\xe7\x86\xe5\x50\x7d\x24\xc8\x0a\x34\x32\x4b\xdb\x33\x46\x27\x70\xb6\xf8\x83\x6d\x91\x81\xb1\xa2\x55\x72\xe7\x01\x24\xcc\xae\x20\x20\x84\x4d\xb4\x90\xcb\x98\x44\x12\x48\xd8\x8f\x4c\xc2\x2c\x1a\xc9\xcc\xd0\x97\x92\x99\xc1\xb3\xd1\x42\xf8\xc1\xaf\x77\x99\x0c\xa1\x54\x4b\x06\xa0\x34\xbe\x9b\x09\x8b\x1b\xf4\x99\x17\x9a\x9d\x32\xcc\x50\x22\x40\xd6\x42\x5a\x53\x13\xae\x30\x67\xee\x9d\x61\xaf\x93\xd2\x9d\xdf\x94\x2b\x4c\xe6\x18\xcd\x84\x79\x91\x87\x7f\xee\xb4\xbe\x13\xbb\x5c\x40\xcb\x52\xa0\xe8\xbb\x68\x9c\x4b\x63\xbb\xf9\x84\x10\x22\xec\x14\x54\xdf\x6d\x15\xe4\x2a\x37\x20\x24\xe4\xda\x72\x5c\x21\x27\xb8\xc8\x2f\xc9\x45\xc3\xe5\x08\xf3\x4b\xd6\x0d\x72\x15\x66\x0e\x11\xc6\xbe\x13\xba\x79\x66\xf1\x56\x82\x24\xec\x7d\x17\x9c\xe4\x27\xc1\x77\xbd\x2f\xf3\xac\xe8\xad\xc9\xd2\x4c\xb0\x71\xf2\x0e\x3d\x0a\x46\xa2\x31\x6f\x6f\x1b\x57\xb6\xcb\x26\x11\xbb\xa4\xbb\x82\xd3\xf6\x18\x89\xb4\xa4\xbb\xb4\xf0\xdb\x4d\x41\xb6\x2d\xfc\x61\x8b\x9e\x6d\x5f\xf4\xcc\xbf\xe8\x99\xb1\xe8\xd9\x5e\x8b\x9e\x6d\x5f\x74\x24\x5c\xe4\xc2\x67\xbe\x85\xcf\x9c\x85\x27\x11\x4b\xf3\x77\x58\x78\x8f\x3a\x74\xab\x0d\x8e\x87\x37\x21\xc4\x7b\x71\x19\x49\xd9\x19\x3c\x1a\xc2\xb3\x8b\x4b\x38\xcb\x89\x4d\xae\x30\xb9\xa0\x43\x9d\x36\x83\x25\xd2\x9e\x35\x5a\x5d\xf2\x93\xca\x76\x68\x6d\xb4\x94\x2b\x14\x74\xad\x71\x08\x44\x55\xd4\xf4\x23\xa1\x39\xfd\x35\xbb\x45\x8b\x84\x76\x1b\x18\xe1\xc4\x17\xda\x8d\x14\xa0\x84\xac\x1a\x92\x62\x21\xd2\x30\x92\xf1\x65\x24\x37\x93\x5e\x7e\x43\x0c\xa5\x4b\x25\x6d\x6b\x47\x85\xa6\x47\xe2\x9b\xd6\x10\x32\x6d\x47\x26\xa4\x77\xc2\x05\x9b\xc2\xd7\x4b\xcb\x0b\xab\x2b\x51\xe8\x91\xd4\xea\x0f\x80\xe4\x59\x4f\x32\xc7\xbb\x8c\x97\xd9\xe9\x6e\x64\x1a\x11\x9c\x51\x96\x41\xd8\xa4\xe2\x72\x23\x74\xb5\x84\x69\x4d\x03\x37\x18\x96\x61\xc6\x61\x8d\x4c\x97\x6f\x5b\x0a\x61\x8a\x65\x35\x53\x97\xcb\xcc\x5a\x14\x55\xa9\x63\x6d\x76\x6d\x2d\x80\xc7\x90\xa2\x4d\xaa\xb0\x2e\x14\xf1\x18\xbd\x2e\x30\x6c\xcb\x99\xd8\x55\x9f\x49\xc0\xb9\x47\xd7\x2f\x75\x60\x92\x7f\xf6\xc0\xbd\xe3\x24\x6d\x7a\x06\x52\x26\x68\x1d\x8c\x0a\x43\xc6\x1f\x35\x48\xf5\x30\xb0\xb6\xc2\xdf\x18\xe6\xda\xd0\x9e\x69\x65\x9e\x27\x43\x60\x3d\x5a\x51\x5f\xca\x67\x39\xf9\x8d\xde\x19\xe6\x29\x80\xac\x9d\x30\x86\xbf\xc5\x0c\x21\xdd\xcf\x0c\xa1\xcb\xbf\xad\x90\xf1\x4f\x7a\xca\xc2\x40\xdb\x00\x20\x95\xa5\x84\xd4\x1e\x54\xee\x8b\xd2\x87\x1f\x59\x92\x05\xc0\x4f\x24\x14\x17\x92\xf3\x87\x24\xa2\x69\x33\xf8\xd0\xa8\x76\xe7\xa3\x60\x6d\xd8\x92\xf6\x03\xf0\x3a\x37\x52\x7a\xd1\xe7\x4d\x78\x86\x49\x60\x3e\xad\x56\x32\x09\xcc\x49\xc3\x44\x73\x38\x14\xad\x68\x8b\x78\xdf\x34\x30\xec\xbf\xd9\x17\x21\xf0\x42\x28\x50\xbb\x8c\x48\x30\x26\x03\x73\x81\x8d\xc9\x05\x02\x28\x03\x1f\x88\x2b\x59\x29\x5b\xee\x62\x63\x88\x93\x60\x3d\x38\xb1\xe1\xa9\x30\xde\x39\x2d\x8b\xc5\xad\x21\xf0\x6b\x89\x60\x6c\x2f\x31\xd5\x92\x18\xa5\x61\xdd\xe5\x9d\x9b\x27\xb2\x3d\xae\x47\xc6\x59\x5a\xbd\x71\xee\x79\x3a\xd8\xb8\x20\x28\x3d\xb1\x66\x85\xb8\x9b\x79\x3e\x34\xe2\x23\xb3\x57\x6b\xa7\xe3\x73\x0c\x18\xe6\x9b\x2c\xbc\xa1\x98\x59\x0f\x77\x65\x79\x50\x57\x1c\x8b\x52\x48\x4f\x84\x21\xcf\x16\xe5\x34\xad\xe7\x22\x11\xf4\xe0\x41\x5d\x4e\x7e\xcd\x1a\xce\xff\x5c\xd9\x42\xba\xf0\x82\x38\x9a\x20\x0a\x56\x29\xa6\xd8\x84\x59\x7f\xce\x31\xbf\x66\xf0\x6b\x8e\x89\x2d\x31\x43\xc4\x27\x8c\x87\x8a\xee\x79\x28\x07\x68\xfd\x78\x8e\x5e\x72\xf0\x1b\xe5\xf0\xe2\x25\x40\x2a\x3e\xd5\xfc\xf8\xb1\x5c\xe5\x13\x7e\x7c\x83\x31\xe6\x23\x18\x5e\x8a\x1a\xc7\x51\x49\xb2\xc8\xf6\xc5\xc0\xab\x38\xa8\xf1\x42\x14\xc3\x03\xe8\xaf\x3e\x03\xa9\x9f\x45\xa8\x36\x2a\xe0\x48\xa2\xa6\x7a\x83\xce\xbe\x30\xee\x1d\x4d\xf0\xd4\xba\x9b\xe0\x39\x7b\x1b\x21\x2f\x43\xd1\x8c\x5c\x1a\xd9\x50\x21\x1b\x82\x26\x61\x57\x2a\xd9\x1c\xae\xdc\xce\xc6\x78\x79\xb7\x37\x65\xe7\x15\x33\x76\x32\x3e\x7f\xfc\x38\xe2\x4d\x8e\x9f\x44\xbc\xf9\x00\x34\x14\x82\xfa\xe1\xae\x70\x69\x3e\xa0\x69\x43\x05\xec\x3b\x6d\x2b\xec\x1a\x41\x05\xbc\xa7\x80\x76\x51\x30\xcd\xe4\xf3\xa5\x1b\xb5\xdb\x19\xc9\xde\xc1\xb0\x7f\x0b\xf8\xe2\x72\x32\x9c\xc2\xbf\xd7\x15\x80\xd6\x04\xa5\x24\x38\x66\x0c\x1f\x1e\xa0\x83\xed\x72\x99\x52\x25\x98\xcc\x9f\xab\x74\xf5\xe7\x7c\xda\xcc\x19\x00\xf1\xeb\x9d\x7b\x05\x7b\xd3\x98\x7b\xd5\x94\xb0\x4d\x22\x8d\xcc\x6f\xd9\xa9\xbd\x03\x34\x6f\xdd\x29\xb8\xac\xf0\xfc\x4e\x16\x25\x6a\xb4\x77\x6c\xc9\xde\x79\x1d\xb6\x76\x59\xa4\x9f\xf3\x1b\x4c\xd1\xb5\xab\xbb\x5d\x21\x83\x7d\xdd\xd9\x9b\xde\xb1\xe7\x98\x52\x83\x36\x14\x1f\x5e\x02\x27\x01\x3f\x9a\xf2\xe6\x66\x91\xc9\x7d\xc5\x17\x3b\x77\x56\x36\x24\xf7\xb6\x31\xce\xe1\x6a\x5e\xc1\x6d\x19\x17\xbb\xf7\xd7\x99\xf4\xae\xa4\x0f\xdf\x38\x69\x29\x9b\x86\x13\x98\xd7\xfa\xc7\x97\x79\x99\x23\xa6\x4d\xbf\xa4\xb7\x0c\xe2\xbf\x30\xe6\xd6\x58\x56\x54\xde\x0d\xe7\xb2\x51\xbd\x1c\x05\xb4\x25\x70\x12\x22\xf8\xb8\x18\xc8\x47\x74\x97\x52\xf9\x4e\x00\x89\x8b\x47\x58\x8c\x74\x21\xaa\xca\x47\xf2\xac\x02\x74\x0b\x17\xe6\x02\x83\x63\x0d\x23\x51\x81\x5f\x0a\xb4\xa9\x67\xe5\x19\xa8\x1e\xe4\xdf\xd6\xb9\x39\x42\xfe\x96\x16\x61\xc7\x2d\x20\x16\x4a\x5f\x03\x26\xce\xc6\xd5\xdb\xf1\x3d\x2f\xb0\xfe\xdc\x42\x00\x64\x5a\xf6\x4b\x17\xe2\xd7\x8d\x14\x16\xda\xcf\xe0\xfe\xcf\xbe\x04\xfb\xe0\x10\x07\xc6\x76\x05\x44\xee\x42\xad\x83\x07\x15\x10\x90\x28\x0c\xf5\x9d\x2a\xcc\x32\x4b\xa6\x40\xad\xc8\xa0\xfc\x55\x0c\x08\xc4\x1d\xc9\xde\x31\x48\x15\x56\x17\x8a\x46\xd2\xed\xd7\x0f\xc4\x81\xd3\x46\x2d\x6c\x22\x64\xbe\x48\xed\x17\x62\xe1\x75\x1a\x37\xf9\x82\x57\x55\x27\x70\x93\xe5\x4d\x7a\x4d\xc9\xa7\xc4\x45\xd0\xb6\xcf\xd6\xcc\xd2\x24\xd1\xb4\x31\x69\x2a\xa0\xa1\x1e\x89\x8e\x27\xe8\x44\x66\xe5\x52\x1c\x09\xd9\xff\x42\x88\xfc\x69\x6f\xe3\xc9\xc5\xf0\xf2\xf8\xb8\x96\xf0\x10\xe2\x6f\x1d\x6e\x90\x2a\x12\x08\xc7\xb5\x01\xf1\xa1\x5d\x81\x68\x1e\xd1\x52\xc8\x54\x52\x78\x81\x3f\xb1\xa5\x68\x3d\xe0\x9d\xc2\xb8\x41\x50\xd6\xb7\x3e\x25\x5a\x87\x3e\x1d\x33\x6d\xa4\x3f\x8c\x33\x4c\x60\xc0\x65\x99\x3b\xa6\x25\xec\xee\xc4\x60\x8b\x53\x01\xb0\xff\xed\xf9\x8b\x8f\x3f\xbd\xfd\x05\x4d\x32\xf4\xc2\xd0\x80\x70\x5d\x4e\x82\xff\x16\x98\xd1\x14\xa9\xa9\x86\x08\xbe\x98\xcd\xc0\x72\xe4\xbc\x88\x04\x84\xe1\x66\xfd\xd1\x6a\x9c\x52\x20\xaf\x8e\xdb\x74\xb5\xe9\xc7\x98\x5f\x1a\xaf\x6e\x74\xcb\xef\x51\x63\x3d\xa2\x42\x0a\x3b\xc2\xa3\xa4\xc7\xc4\x3a\x4d\x2e\xce\xe1\xdf\x62\x2c\xc9\x39\x5e\x78\x2c\xc5\xa9\x73\x1d\x5a\x00\xf3\xb5\x3b\xf4\x5f\x8d\x2d\xa4\xca\xbf\xaa\x2d\x74\xab\x2e\xeb\x9b\x00\xa3\x46\xaa\x45\x3b\x67\x08\x9a\x25\x54\x7d\x9e\xc8\xf5\x3a\x37\xd6\x6b\x24\x96\x75\x1e\xcd\x50\xfe\x68\x34\x57\x03\x72\xb1\x9a\x1b\x72\x73\xba\x9d\xa1\xb7\x9d\xcc\x69\x87\xb1\x9c\x82\x42\xfa\xe9\x83\x41\xc2\x66\x00\x83\xf8\xd7\xf7\x1e\xd3\xe1\x05\x7a\x2b\x2e\xaa\x01\x67\x4b\x08\x03\xd2\x6a\xf6\x9e\x8a\xe3\xf9\xac\x77\xda\xfb\x17\x52\x0d\xf6\xf4\x81\x0d\x1e\x20\x94\xf5\x2e\x44\xc9\x25\xd4\xf9\x39\x43\x09\x23\xa6\xe2\xa3\xfc\x7d\x45\x83\x36\x3b\xc8\x0d\xa1\x96\x4b\x7e\x19\x19\xbd\xe0\x69\xea\x3d\xc5\x7f\xb1\x8b\x17\x64\x2c\xd6\xa3\x23\x86\xed\xe3\x11\x82\xe2\x97\xea\x04\xb1\x36\xd2\x6c\x5f\x60\x03\xb3\xcd\x65\xd6\x7b\x2a\x20\x0d\x1b\xfd\x90\x61\x0a\x40\x16\xe8\x69\xa4\x12\x3c\x60\x98\x83\xf7\x73\x60\xe1\xf8\x87\xcc\x23\x28\x1b\xf7\x8d\x18\x20\xa2\xf7\x94\x33\xd2\x3f\x6b\xf7\x23\xd3\x0e\x92\x93\x75\xe6\x4e\x1d\x57\x63\xcd\xf9\x34\x8c\x16\x01\x28\x76\x36\x64\x8c\xa8\xa1\xd1\xe3\x8e\xf6\x2e\x44\xad\x4b\xfa\x8a\x16\x7b\xb2\xc8\x50\x20\x82\x6f\xe5\x64\x2f\xe9\x4c\x6d\x36\x42\xf9\xee\x62\x5e\x40\xf7\xa4\x05\x77\x11\x2f\x94\x9f\x47\x6d\xbc\x0b\xc5\x4f\x22\x07\xed\x42\x19\x69\xb5\x1d\x64\x0f\x57\xda\x13\x45\x16\xd3\x35\xb2\x5f\x4a\x49\xba\xd0\x28\xcc\x34\xdf\x22\xea\x76\x2b\xd5\xab\x53\xba\xaa\x2a\xba\x36\xca\xc1\x7b\xfc\xc1\xf1\xb6\x2b\x0c\xb6\x30\xf8\x85\x49\x57\xe8\x46\xde\x12\x1f\xd3\x6b\x14\x31\x0f\xfe\xb3\xfe\xaa\x14\x87\x7a\x12\xf2\xba\x5c\x88\x72\x96\xeb\x3e\x58\xad\x49\xa3\xb8\x52\x74\xda\x8b\x05\x10\x40\xe1\x1d\xa0\xf4\xd5\x22\xbd\x25\x53\xea\xe0\xf9\x6a\x15\x44\xfc\x41\x7c\xb1\x88\xd0\x2e\x4c\x69\x20\x26\x03\x49\x44\x47\x9a\x9c\xee\xc3\x86\x88\x67\xd7\xd1\x93\xdd\x26\x44\xd2\x81\x3f\xe7\xcd\x1c\x95\xf7\x22\xba\x59\x5a\xd4\x94\xc5\xf2\x23\x79\x17\xc1\x05\x5d\x4c\x6d\x07\x39\x65\xd1\xea\x49\xa7\x43\xb9\x04\x22\xf7\xd5\x3a\xe2\x44\x03\x6e\x79\xca\xe5\x08\x33\x06\x91\xb0\x12\x04\x8b\xbd\x68\x44\x2d\xb8\x6b\x06\x3b\x4f\x56\x1c\xe6\xaa\xc7\xe7\x8f\x7e\x8c\x68\xf3\xe2\xf3\xb3\x1f\x23\x7b\x1f\xe3\x47\x67\x0e\xc9\xf1\xe8\x00\xb1\xc8\xfe\xb0\x42\xb0\x00\x68\xa6\xf9\x98\x37\x8b\x4c\x40\x83\x34\x4f\x63\x6e\x82\xcb\x04\xd8\xbc\xe1\xc3\xf0\xc7\xf2\xab\x05\x39\xb2\xfc\xa7\x62\xb5\x96\x30\x25\xc2\xdc\xa3\x4c\xc4\x80\xb4\x95\x24\xfa\xf9\x68\xf0\x9d\x9e\x4d\x3f\x22\xb1\x22\x82\xdc\x3b\x24\x8c\x88\x71\xef\x02\xe1\x74\x2b\x10\xbe\x20\xe6\x55\x42\xe1\x1c\x28\x55\xf2\x80\x00\x58\x94\xb4\xc7\x2a\x0a\xac\xce\x2f\x6d\xed\x4c\xdb\x85\x63\x16\x1e\x89\x64\x62\xc8\x63\x60\xb8\x45\xed\x69\x88\xd7\xfd\xbb\xb4\x4a\x97\x75\xc8\x16\xeb\x74\xe0\xc7\x33\x49\xb3\x60\x3c\x2c\xc4\x16\x51\xf0\x8f\xc1\x89\x7a\xdf\x8f\x65\xf9\xf1\x71\xab\x2a\x8a\xce\xda\x30\x6d\xfb\xff\xe3\x94\x06\xc6\x2c\x94\x4a\x06\x73\xe2\x89\x31\x40\x8f\x18\x02\x57\xfe\x06\x7a\x6e\x4c\xac\xfd\xe9\xaa\xca\x3f\x53\xc2\x69\xfe\xa9\x90\x14\xff\xd4\xf7\x88\xef\xf4\xdc\x4d\x70\xcd\x85\xeb\x44\xd7\x71\x69\x95\xd7\x1d\xe5\x5d\xc7\x6e\xd2\x51\xbe\xf0\x1e\xc7\xa9\x73\x1c\x0d\x44\xec\x3d\x8c\x5e\x18\x8c\xcf\x9f\x10\x92\xb7\x8f\x04\x1c\x55\x32\x81\x72\xa0\x1f\x8a\x1f\x46\x3e\xe0\x87\x17\x64\xfb\x64\x9c\x20\x28\xa2\x2b\xc1\x3a\x0e\x30\x92\xe1\x21\x28\xe0\x5b\xf2\xc0\xdd\x19\xd3\x03\xd6\x16\xaf\xdb\x09\xc1\x36\x01\x2d\x49\x2c\x35\x78\x6a\xd0\x1c\xd4\xf9\x7f\x01\xff\x8a\x64\x00\xd7\x64\x6a\xd6\x53\x73\xa3\x53\xdc\x48\xcc\x53\x5a\x98\x87\xb0\x4c\xba\x6e\x4a\x4c\xe5\x26\x6c\xf5\x2d\x24\xa0\x49\xa8\xf5\x36\xec\xe0\x5e\x52\x8a\xf1\x59\x38\x2f\x74\x7b\xab\xd6\x27\x24\xf9\x68\x63\x1a\x71\x18\x5e\x30\x39\xd1\x85\x71\xf2\x1d\x18\x87\x20\xc6\x46\x3b\xea\xea\xab\xa3\x40\x4a\x60\x99\xac\x9b\xe2\x42\xe9\xf7\x6b\x0b\x1f\xa9\x2a\x97\xd1\x6e\xc7\x48\x34\x64\xbb\x91\x3e\x5e\x7d\xd4\x33\xdb\x1d\xb9\x86\x35\xda\x21\x4c\x84\x3c\x68\x21\x12\x6c\xa4\x3d\x1a\xcb\x6d\xb1\xd5\x10\x7e\x33\x27\x9a\x83\xa8\xde\x17\x0b\x14\xa2\x78\xfd\xb2\x3d\x88\xab\x31\xf1\x15\xc5\x87\x33\xf0\xd5\x42\xb0\x6f\xaa\x10\x7d\x7f\x04\x96\x8c\x67\x03\x92\x01\xfa\x20\x13\x58\x3b\x83\xd9\xd4\x88\xf5\x60\xbc\x1a\x15\x68\xac\x03\xd0\x6b\x2e\x17\x9d\x8d\xfb\xfb\x00\xb0\x21\x1a\x98\xbe\xad\xf2\x9b\xbc\x48\x17\x1f\x39\xcf\xad\xf6\x65\xde\x85\x8c\x5f\x90\x08\x33\x0e\x68\xd5\xe0\xef\x4b\x43\xce\x95\x77\xd3\x2e\xfe\x57\x06\x62\x66\x3c\xde\x20\x48\x9e\x5e\xa7\x55\xb0\x69\x7f\x52\xaf\xd2\xa2\xeb\x9b\x00\x65\x33\x28\xaa\xea\xef\xdd\x15\x2e\xc8\xe9\x97\x2a\x5d\x1d\xd2\x17\xeb\x49\xa6\x08\x60\x80\xf8\xea\xc5\xed\x07\x23\xf7\x5c\x7c\x77\x75\x35\x6f\x96\x8b\xb8\xd8\x60\x9e\xbb\x56\xa3\xb9\xdd\x62\x0e\x0b\x77\x2a\xa5\x9b\x34\x8b\x38\xf8\x20\x7e\x96\x05\x43\xe4\x6a\xc0\x12\xd3\xcd\x9e\xcd\x2d\xca\x1b\xc0\xc7\x18\xfd\xa1\xc1\x5f\xb4\x49\xa2\xed\x46\x35\x4a\x60\xe1\x02\xbf\x77\xc4\xad\xa5\x43\x84\x8c\x48\xa0\x6b\x8f\x7c\x63\x22\x9e\xc9\x37\x81\x8e\x45\x56\x48\x3f\xd8\x18\x81\x82\x07\xaa\xf8\xfe\x9e\x2f\xd4\x1d\x37\xaa\xc3\x21\xf9\xb1\x27\xbc\x7c\x18\x79\x70\x2e\x94\x3f\x8e\x3c\xe8\x5b\xf0\x4f\xdb\xaf\x68\x8b\x83\xda\x76\x75\xeb\x6b\x26\x3e\x37\x6e\x56\xe7\x1e\x3d\x40\x45\x63\x90\xd2\x4a\x94\x57\x76\x5d\x44\x69\xe7\x45\x54\x7b\x6f\x94\xf5\x76\x1a\x56\x62\x01\x79\x9f\xd4\x7b\x5c\x06\x77\x35\xb0\xef\x6f\xc9\x98\x2e\x5d\xd4\x18\xdb\x58\x62\xe5\x0f\xeb\x6b\x2b\xcc\x0e\x59\x1e\xaf\x2a\xd2\xce\x8a\xf0\x6d\x22\x46\x2b\xc5\x82\x27\x8e\x1e\x85\x56\xb0\xce\x35\xc7\x23\xc0\xf0\x0d\xcb\x10\xcd\xfd\xd4\x7b\x14\x4d\xd8\x2f\xd1\x69\x62\x46\x96\xe3\x61\x3e\x58\xa6\xab\x50\xd5\x95\xb7\x92\xa8\x2f\xe4\x8c\x51\x40\x79\x47\xe1\xe3\x3e\x39\xf1\x91\x90\x5c\xb7\x0f\xbf\xec\xf6\x51\xa4\xae\x5e\xd7\xf5\x02\x9a\xcd\x26\xbf\x66\x53\xe1\xc8\x2c\x70\xb7\xb9\x08\xc7\xc7\x61\xad\xa4\xf2\x7a\xe8\xb2\xc4\x6e\xbe\x56\xa2\x7e\x5d\x53\x96\xb8\x35\xa5\xf4\x5f\xd7\x94\x25\x56\x4d\x34\xc2\x51\x61\x44\x06\x41\x1f\x43\x8d\x17\x24\xe2\x94\x57\x13\x1a\x8b\xd4\x48\xe7\xea\x58\xe4\x29\x8b\xbd\xaa\x28\xd3\xf7\x2a\x4a\x66\x5a\xd7\xaa\x7d\x0f\xbb\xdb\xdf\xb5\x26\x9b\xee\x5b\x90\x92\xed\x59\xa1\x92\xfc\x6b\xda\x24\x07\x70\xd6\x41\x8e\xc4\x31\xa0\xa6\x42\x21\x3d\x7c\x02\x4c\x7a\xbb\x82\xdf\x98\x36\x26\x88\x88\xcb\x9f\x97\x0b\x1c\x55\xf0\x49\x56\xd9\xb4\x19\x00\xa7\x35\xb9\xea\x5b\x5a\x7b\x27\xab\xec\x6e\x4d\xc2\xc5\x96\xd6\xde\xcb\x2a\x80\xe2\x3d\xed\xb5\xaf\x47\x71\x92\xdb\xac\x52\xc0\xda\x5a\xd4\x20\xc6\xe2\xb9\xfd\xdd\x29\xbf\x28\x0b\x71\x84\x8d\xdb\x86\x4b\x3c\xed\xce\x87\x62\x27\x14\x1a\xd9\x39\xf1\x1d\x93\xfe\x85\x5e\x8b\xcc\x41\xff\x46\xf1\xaf\x83\xd7\x55\x96\x61\x8a\xbe\x3d\x96\x55\x60\x92\x2d\x1d\x3c\x97\x35\xec\x3e\xf2\x6a\x32\x98\x89\x7e\x06\x45\xd6\xec\xd1\x17\xeb\x9b\xba\x67\x82\xaf\x77\xb7\x22\xf1\xd5\x96\x96\x5e\xc8\x2a\x98\xb1\xa7\xdd\xde\xaa\xeb\x34\x2c\xd0\x19\x78\xbf\xa3\x02\x28\x4e\x0e\x80\x30\xdd\x75\xf9\x15\x7b\x0b\x3e\x7c\xf8\xd9\xbb\xa5\x1e\x72\x21\x5b\x2c\xf2\x55\x8d\x6a\x40\x0f\xbd\xa2\x90\xca\xc6\x07\xca\x72\x2c\x3c\x80\x9a\xa0\x2d\x88\x38\xfa\xb9\x82\xac\x4d\x8b\x72\x58\xef\x4b\x39\xec\x24\x02\x0c\x2b\x02\x71\x99\xd3\x0d\x7e\x80\x11\x81\x5f\x18\xe6\x5a\x5c\x30\xeb\x9d\x17\x33\xb4\xfc\xc4\x24\x1e\x70\x99\x87\x2e\xdf\x6a\x8a\xba\xfe\x94\xa5\x00\x02\x2c\xd5\x52\x22\x33\xf1\xee\x67\xcc\x17\x63\xca\xcd\x14\xc1\xb2\xd4\x15\x0c\x8e\xd6\xcb\xee\xba\x5c\xad\x96\xd5\xaf\xbc\xc4\xc4\x6c\x2b\x31\xa1\x45\x17\x9a\x9e\x58\x19\xe2\x30\x60\x3f\x45\x07\xe4\x78\xaf\xca\x27\x2d\x31\xd9\x6e\x12\x64\x9e\xe5\x37\xf3\x26\x16\xd2\x32\x4e\xe6\x4d\x45\xa7\xc3\xb3\xb3\x5d\xa1\x52\xc4\x57\x80\x2e\xc8\x62\x50\xc5\xd7\x43\xab\x9c\xfc\xbf\x10\x41\x69\xd8\x7d\x4f\x45\x5d\x86\xd5\xed\x46\xd9\x7e\xeb\x9b\xdb\x5d\x4d\x9d\xf9\x1a\x2c\x2d\x80\x16\x1b\x7c\x23\x27\xfe\xf2\xed\x1b\xcc\xb0\x1e\x8a\xdc\x15\x08\x43\x1f\x26\x55\xb9\xc0\xe8\x11\x35\x3d\x7c\x2c\x57\x27\x0d\xa6\x69\x82\x9b\x9b\xd7\x86\x98\x5e\x7e\xc9\x05\xf6\x3a\xb5\x3b\x97\x31\x09\xd6\xf4\x86\xac\x7b\x64\x74\x00\xdd\xe1\x5e\x63\xd4\x63\x72\x87\x20\x29\x0f\x5e\x90\x16\xd9\xe1\xe9\x5a\x53\x22\xdb\xa1\x00\x16\xd7\xf8\xfa\xa0\x45\x35\xb2\xcc\x8b\x15\xa4\x36\x46\x22\x2e\xe0\x94\x83\x9b\x22\x85\xa2\x0a\x92\x26\x5a\x0c\x4c\x3b\x28\x16\x57\x74\x51\x40\x1d\x52\x80\x4c\x8b\x25\x30\xca\xa4\x90\x37\x60\x46\x15\x0f\xb9\x24\x4f\x93\xc7\xda\x59\x27\x2f\x91\x8d\x9c\x64\x27\xf9\x48\x24\xf8\x68\x4b\x53\xef\x7e\xcd\x6e\xe3\xd2\x34\xbd\x30\xc3\x96\x0c\x29\x62\x09\xe0\x28\x1d\x99\x1c\xc3\x95\x74\xb4\x56\x8b\xd6\x4e\x82\xd3\xe0\x64\xcd\x17\x0b\xe7\x0c\x8f\xb0\x89\x58\xb4\x74\xb1\xbe\xdc\x90\x8d\x3e\x06\xb9\x95\x61\x50\xc6\xbb\x29\x1d\x31\x46\xba\xa4\x5a\xb7\x49\x29\xe8\x1c\xdc\xd1\x00\xd3\x65\x34\x69\xae\xa0\x22\x36\xd6\x8e\x41\x27\xca\xf8\x3b\xf1\xfe\xfc\xd1\x06\xd0\x3c\xa6\x4d\xfa\x4d\x83\x10\xd5\xf5\x40\xa8\x55\xfb\xfa\x9a\x39\xd7\x97\xa3\x02\xdc\xce\xab\x9a\x28\x1e\xde\xfd\xb8\x4b\xd4\xdc\xbe\x4f\x60\xaa\x8f\x22\xcf\x6d\x02\xe5\x4f\x6c\x0e\xb7\x7d\x3b\x46\xee\x4d\x16\x0f\x1f\xba\xec\xef\x01\xe6\x70\xf2\xf2\x0c\xcd\xdb\xd3\xb9\x16\x35\x43\x8c\xa6\xf9\x1e\x36\xd8\x16\xae\xd6\x5e\x25\xcf\x76\x56\xd8\x5a\xa3\x40\x78\xa8\xbc\x90\xe8\xd1\xc5\x8d\xa6\x31\xb8\xd8\x0d\x01\xd5\x67\x97\x32\x3d\x11\xfa\xfb\xd4\xad\xb7\x8a\xd3\x22\xc4\xb0\x4d\x84\x69\x7d\x3f\x4a\x07\x68\x8f\x68\xca\x20\x51\x31\x4f\x21\xae\x1d\x05\x90\x78\xb3\x03\xf7\x58\xad\x03\xde\x21\x42\xb1\x48\x24\x64\x07\x14\x1e\x80\x05\x92\x6a\xec\xbb\xc4\x90\xd4\x31\x60\xc5\xac\xcd\xb7\xb1\xd8\x88\xd9\x85\x9e\x47\xe7\xd3\x16\x2b\x89\x81\x9c\xd6\x34\x0b\x3f\x61\xa9\xd7\x70\x23\xa7\x8d\xe1\xc9\x09\xd9\xa0\x7f\xc7\x49\x12\x48\x9d\xfc\x29\x6a\xc5\xb0\xdc\x43\x82\xae\xac\x9e\x0b\xcf\x89\xee\x1e\x5e\x93\x23\x93\x16\x95\x03\x7c\x00\xdc\xb2\x24\x71\x04\x3c\x23\x53\xde\xd9\xd0\x2e\x61\x24\xac\xd1\x49\x8a\x02\xc9\xed\x44\xef\x56\xa9\x98\xa5\x9d\xa2\x73\x03\xf8\xe0\xd1\x9e\xf2\xab\x03\x0c\x4c\x3b\x55\xc1\x1a\x29\x11\x8d\xff\xa7\x1c\x7f\xdd\x1a\xa7\xd7\x4b\x94\xba\x87\x57\x13\xa5\x6b\xe7\x8d\xd3\xaa\xab\xbc\x69\x2c\x1a\xf7\x10\xfb\x02\x53\xdb\x66\x1a\x1a\x68\x9a\xb5\x8c\x82\xb9\xea\xd8\xb2\x3e\xe0\xc9\x44\x01\xf4\xfe\x41\xcc\x6b\x3f\x92\x56\x70\x3c\xc1\x2e\xea\x55\x93\x2d\x34\x7f\x87\x6e\x29\x27\xeb\x1a\xc3\xdc\x1b\xdd\x1f\xfe\x31\x9f\xae\x7f\xcd\xec\x1c\x10\x40\x0d\x0e\x1f\x12\x0d\xf9\x65\x9e\x4f\xe6\xe8\x8c\x27\x64\x52\x34\x74\x95\x24\xc2\x50\x14\x8d\x82\x07\xac\x6a\x31\x2b\xa2\x4a\xa2\x96\x36\x83\xa1\xfd\x2e\x52\x8a\x0b\x74\x2b\x13\xfa\x97\x9a\x6d\xb2\x76\xd7\x8c\xd6\x9c\xcb\xd2\x1e\x17\x94\x92\xb9\x7d\x9b\x7e\x54\x4b\x2e\x7c\x91\x1e\xfe\xa0\xa7\x37\x0e\xdb\xa2\x4b\x68\x49\x19\xec\x87\x40\x27\x3c\x3a\x33\xea\xaf\x07\xca\x80\x3f\xec\xc7\xc1\x1f\xd3\xc9\xaf\x70\xd8\x27\x19\x2f\x00\x50\x44\xf7\xf7\xc1\x4b\xca\xb9\xaa\x4a\xc6\x6a\x64\x71\xf0\xa9\xc8\xa7\xf0\x69\x3e\xcb\x01\x60\x64\x85\xe3\x63\x55\x43\xee\x0a\x2b\xca\xb6\xe8\xc9\xc4\xac\xec\x45\xf0\x0b\xe3\xb6\x9a\xaf\xf8\x90\x1d\x01\x8d\xd4\xbf\x74\x72\xf2\x44\xf8\x88\x1f\x5d\x8d\xd8\x12\x0f\x31\x64\x83\x3c\xe3\xc3\xc5\x41\xba\x45\x19\x6f\x7b\x59\x00\x5c\xbe\x2c\xbf\x14\xe6\x45\x00\x45\x78\x3f\xf0\xd2\x18\xe5\x5c\xd2\x42\xa3\xae\x59\x8d\x85\x48\x00\x65\x0e\xa3\xad\xa4\xd9\xc1\xea\x7f\xa7\xfd\xc7\xdf\x6f\x25\xd8\x3a\x71\xf2\x01\xf6\xef\x06\x4e\xb6\xc4\x0b\xa5\x17\x1b\xa6\xfb\x60\x43\xa2\x36\x15\x32\x2c\x2f\x3b\xc9\x8b\xdc\xd0\x63\x32\x95\x81\xf4\x43\x07\xed\x00\x94\x87\x26\x39\x8a\xe4\x6e\x05\x07\x38\x2f\x6e\x7e\xce\x66\x8a\xaf\x5b\x4a\x6c\x8c\xe7\xe3\x24\x58\x01\xc9\x6d\x31\x43\xdc\x87\xb8\xf2\x33\xe7\xca\xb7\x2b\x74\xdc\xfd\xff\xa0\xa1\x34\x8b\xea\xe6\x76\xb1\x95\x08\xd8\x75\x77\x37\xed\x7b\x3b\x15\x00\xd7\x02\x12\xff\x65\x4c\xbb\x7d\x80\x25\xfa\x7e\xf2\x27\x45\x3d\x7b\x2e\x60\x61\xb3\x50\x6f\xbb\x98\xdd\xeb\x57\x7d\x35\xf1\x02\xd5\x62\x2b\x50\x49\x9d\xa9\x84\xa7\x89\x71\xb9\xa6\xd2\xff\xc4\x12\x13\xd5\xdd\xd6\x54\x1e\xe1\x05\x19\xf7\xa1\x4f\x31\xdb\xc7\xa0\x66\x41\xc4\x38\x94\x4c\xb7\x5b\xbe\xe7\xad\xe8\xc1\xbf\x3a\xe3\x82\xc7\xec\x40\x5d\x53\x88\xcb\xb9\xd7\x50\x5e\x58\xc6\x1d\xe6\xdc\x59\xdd\xc4\xbb\x5c\xc6\xd8\x3f\x99\x71\x70\xbd\x28\xd1\xd6\x3a\x28\xd0\x79\x67\xe3\x1a\x1c\x50\xc5\x8a\xe2\x99\xd6\xa4\x3b\xf3\xb0\x34\xde\x33\x82\x2c\x7d\x33\xc8\xa7\x36\xa9\x8b\x9e\xa1\x2f\xf1\xd6\x19\x66\x0f\xff\xa0\xe8\x5e\xa4\xf0\x99\x1c\x17\x8f\xc8\x88\x43\x4b\x46\xf8\xf5\xdd\x77\x8e\x54\xb2\xf3\x79\xf4\x29\x20\x76\xdc\x37\xdc\x80\xef\xba\xd9\x76\x55\xec\xa1\x6b\x11\x0d\x8b\x55\xc4\x35\x76\xcf\xfb\xc2\xb9\x60\x5c\x05\xf5\x76\x5b\x31\x51\xf7\xc9\x70\x07\x5f\x6f\x52\xf5\x1e\x36\xdd\xb9\x3d\xf6\xf6\x27\xd1\xf8\x64\xfb\x01\x6e\x1a\x40\xd4\x75\xf0\xbb\x98\xc5\x1a\xca\x24\xd5\xb0\xbb\xa8\xec\x06\x67\xa2\xc8\xdf\x6c\xdb\xdc\x42\x91\xd2\x7c\xf6\xa7\x26\x5b\x4a\xc1\xbb\x83\x2c\xdb\x1a\x77\xf1\xc2\x96\x41\xb4\xec\xcc\x84\x02\xff\xf7\xb4\x83\x16\x83\xf5\xb3\x28\x64\xed\x85\x9d\xda\xd2\xf6\x54\x1b\x89\xb9\xe8\xd5\x98\x40\x8d\xf8\x55\x1c\x0c\xae\xd0\x92\x54\x68\x43\x6b\xed\xe0\xa6\xf5\xc8\x62\x13\xb7\x7e\x55\xab\x9d\xde\x2e\xab\x88\x32\xbf\xfc\x53\x69\xfb\xdb\x81\x3c\x50\xfe\x99\xf9\xc5\x93\x25\xe3\xb2\x3c\x12\x8e\x32\xb9\x72\x4d\x64\x11\x08\x1b\x07\x48\x7c\x49\x0b\xc8\x41\xdb\xc3\x8b\x3c\x62\x0d\x26\x06\x8b\x40\xc7\x79\x8f\xdc\xb5\xd8\xd9\xef\x49\xe1\xe9\x59\x38\xee\xb1\x40\x54\xf6\x6e\xee\x07\x86\x25\x09\x73\x8c\xd3\xeb\x7b\x09\xe3\x83\x97\xde\xa8\x17\xbb\x46\xd3\xb4\x47\xd3\x88\x45\xa0\xd1\xec\x85\x11\x31\x41\x31\x0b\x3a\x5b\x75\xd9\xaa\xc9\xae\x2e\x2c\x9d\x94\x0d\x9a\x47\xb4\x63\x42\xdd\x66\xab\x86\xd9\x37\x98\x53\x25\xf9\x25\xec\xbc\x0f\x4e\x07\xee\xeb\x94\xc7\x55\x7b\x79\x9b\x2d\x36\x52\x7b\x55\x9e\x94\x37\x1d\x32\x2c\xe3\xa4\xb4\xd5\x9c\x87\x7b\x00\xec\xb4\x68\xb2\x85\x46\x4f\xce\xa2\x36\x9a\x82\xe2\x87\x91\x07\x1b\x42\x53\x67\xbb\xaf\x9a\xc7\xbf\x87\x1f\x41\x17\x15\xea\x4a\x7e\x1b\x4b\x68\x74\x88\xf1\x93\x31\x39\xc3\x00\xca\x16\xf2\x34\x4c\x69\x0a\x98\x74\x91\x59\xaa\x64\xaf\x9a\xcd\x90\x42\x58\x5d\xa2\xac\x98\x3b\x91\x9c\x83\xdd\xac\xcf\x50\x0d\x44\x27\x98\xe0\x5a\x5d\x23\xad\x1e\x45\xa2\x4b\x69\x39\x9a\x5e\x2b\xbb\xff\x76\x9b\xed\xba\x8a\x46\x95\x9d\xd5\x4a\x76\xb5\x4b\x5c\xda\x68\xef\x39\xef\x41\x16\xd2\x59\x3d\x08\xb2\xf8\xdc\x2e\xd7\xfc\x76\xc3\xfa\x4e\x98\x3c\x20\x7a\xc3\xb7\xab\xf3\x2d\x77\x14\x4d\x43\xfc\x46\x6b\xf4\x43\xf8\x2a\xd9\xb9\xcd\x59\x6d\x37\x11\xcf\x7f\x9b\x89\x38\xc3\xb0\x69\x1f\x2e\xd3\xc2\x23\x82\xac\x77\x78\x01\x44\xb6\xf3\xc0\xff\x8f\x14\xfb\xdd\x16\xf2\xdb\xed\xd4\x6d\x69\xde\x3e\x6b\xb8\x39\xd4\x96\xde\xe3\xb1\xb1\x4f\x1f\x5b\x35\xf5\x07\xa8\xe5\x0f\x56\x8a\x63\xe6\x6c\x2b\x1e\x9c\xc2\x57\x1e\x5b\x7e\xc7\xfc\xd8\x1f\x2b\xae\x83\x2c\x4a\x25\xa3\x8b\xf6\x5d\x2a\x90\x01\xa6\xf1\x2c\x06\xe2\x9c\x25\xcc\x59\x47\x99\x72\x28\xde\x43\x69\x2d\x4d\xb0\x83\x6e\xf1\x12\x50\x64\xdf\xa2\xaf\xce\xf6\xd2\x57\xef\xd1\xbf\xc1\x9d\x75\xf2\xb3\xbf\x8b\x01\xb5\x0f\x45\xc2\x47\xdf\xa8\x6a\x7e\xfc\x6d\x96\xd6\x5d\x38\xd7\x35\xbc\xb6\x99\xba\xdf\x8f\xf8\x30\x57\xc0\x32\xbf\xee\x20\x35\xa4\x68\x15\x91\x2c\x1d\xcd\x10\x03\x90\xb0\x4a\xd8\xbc\x5c\x71\xa3\x09\x78\x61\xb0\x8a\x3a\xf1\x57\x38\x44\x23\x80\x57\xfe\x5e\x97\x3b\x35\xcf\xed\xfe\xb2\xfb\x9e\xdf\x5f\x7f\xf9\x6d\x44\x00\x01\xc8\x2e\x43\x3e\xd3\xa5\xcd\x08\x5f\xdd\x9c\x84\xd9\x38\xe8\x85\x14\xac\xb3\x1f\xc4\x41\xd0\xd7\x6e\x68\x8e\xa1\xbe\x0e\x30\x93\x5a\x31\x38\x7c\x9a\x4d\x8f\xe9\xbe\x13\x56\x43\x6b\x3c\x27\x1d\x71\x38\x16\x76\xb9\x94\x21\xac\x44\x28\x12\x1b\x3c\x9d\x26\x58\xb0\x4a\xd0\x53\xc8\x28\x60\x56\x38\xbc\x81\x08\x4d\x16\xb2\x59\x7a\xd4\xbe\x0c\xd0\x16\x80\x95\x61\x14\xc3\x80\xeb\x9d\x04\x14\xbb\x18\x63\x6b\xa3\xf7\xbc\xf4\xe3\xef\xf8\x7a\x83\x9e\x69\x38\x00\x8e\x21\x66\x0f\x40\x07\x41\xdb\x7b\x0c\x95\x1e\xc5\x22\x9b\x35\xee\x18\x00\x22\xea\xb2\xe8\xef\x1c\x0d\x07\xc1\x31\x47\xb3\x1e\xa8\xd8\x57\x66\x27\x5c\xd1\xdb\x30\xd6\x40\xbb\x0c\x2b\x94\x9b\x3b\x11\xdd\x25\x5b\x12\x77\x75\xd9\x0c\xca\xc5\xf4\x24\xe8\x71\x52\x9f\x29\x05\x6a\xc0\x08\x05\xc1\x49\x73\x41\x31\x6e\x2e\xcd\xae\xa1\x2e\xf7\x2c\x83\xc6\xf1\xf7\x51\xab\xae\xee\x5e\x29\x5f\xec\x11\x90\x1e\xd5\xd8\xa5\xe5\x8e\x0a\xcb\xb2\x99\xda\x55\xf2\x41\x86\x97\xae\x12\xfe\xea\x97\x99\xfc\x5e\x05\x1b\x52\x33\x28\xf5\xb3\xb4\x45\x43\xdd\xa5\xee\x67\xcd\xf1\xef\x6c\x78\xa9\x35\xdd\x42\xef\x3d\xdb\xac\x5b\x10\xee\x60\xad\x16\xa4\xf7\x29\xbd\xdf\xda\xc2\x92\xa2\xed\xb5\x1a\xc0\x20\x7c\xe6\x92\x88\xb8\x48\x6d\x4d\x81\xa5\x21\x57\x10\x7c\x41\x46\xe3\x31\xee\x2c\x53\x1f\xca\x3f\x81\xcb\xa4\x43\x43\xa4\x7c\x03\xb8\x5c\x3a\x13\x44\xc1\x9f\xca\xba\xe1\xb2\x39\x3c\xa1\x24\x95\x56\x97\x4a\xa4\x73\xb8\x34\x27\xe7\x52\x79\x06\x2e\xa3\xb6\x4a\x42\x4f\x44\x8a\x11\xad\xa9\x58\x8e\xea\x18\xef\x1e\x29\x87\x84\xac\x22\x17\x1e\xc9\x60\x74\x74\x06\xe8\x8c\xaa\x9b\x6b\xa4\x0d\xe0\xed\xe5\x74\xeb\x49\x65\x80\x59\x6b\x35\xd0\x51\xca\xc2\x46\x2a\x35\xf0\x9b\x89\x8a\xcc\xd5\x11\x91\x48\x2d\xba\x14\x2c\xe5\xc5\xcd\x60\x30\x08\x44\xe6\xdf\xdf\x12\xb3\xc3\x12\xd0\x74\x28\x00\x0e\x0a\xf0\x61\xc4\xaa\xf2\x5f\x2c\x74\xe5\x99\x31\x3f\x1e\x1f\x66\x7d\x77\x8a\x97\xea\x29\xdf\xd9\x0f\xea\x79\xba\x58\x94\x5f\x5e\xfd\x6d\x9d\x2e\xec\xe4\xea\xbb\x2c\xe2\x64\x84\x4e\xa4\x05\xe8\xc8\x7f\x85\x3d\x21\x3f\x73\x33\xf5\xf6\x00\x3b\x53\x8d\xfc\x0c\x28\xee\x5d\xca\xd6\xb4\xed\xef\xf0\x98\xbc\xe0\x28\x2c\x58\x29\xec\xab\x24\x69\xde\x46\xf6\x6a\x02\xd6\x42\xa5\x7e\x17\x0f\x95\x21\xbe\x89\x30\x73\xe3\x91\xe9\xb3\x4c\x71\x5c\x10\x24\x76\xac\x55\x3c\x7c\x4c\x6b\xbf\xcb\x70\xca\xa5\x36\x30\xe8\x43\xd8\xf4\x64\x5a\x81\x72\xd6\xcb\xcc\x9c\x5e\x1f\x6f\x57\x99\x9d\xd7\x0b\xa3\xa8\x62\x50\x20\x24\x2a\x7b\x69\x6d\xe4\x14\x0f\x8c\x54\x1c\xb9\x6a\xdd\x93\x9d\x37\x3b\x3e\xc6\xd3\x8a\x7e\xc2\xfe\xae\x3e\xac\x57\x19\x60\xaa\xaf\x2b\xf4\x96\xc1\xe6\x28\xb9\x7b\x96\x53\x1c\xf3\xeb\xac\x87\x5f\x63\xe8\x1b\xdd\x77\x44\x19\x6b\x00\xa7\x88\x1e\xfa\x9c\x5a\x9a\x53\x49\xc8\x58\xc1\x4c\x54\x86\xd0\xbd\x99\xf9\x0b\xd9\x1e\x58\x9d\x35\xe6\xed\x89\xa5\xf5\x4a\x94\x15\xeb\x65\x56\x51\xb4\xff\xa3\x61\xf4\xa5\xca\x1b\x7e\x3e\x43\xab\xde\x59\x7e\xb3\x16\xef\xce\x36\x68\x44\x40\xb9\x19\xaf\xae\xa8\xd1\xab\x2b\x98\xd6\x86\xad\x9f\x0d\xd2\x56\x2d\x4d\xe3\x46\xd4\x3d\x73\xb3\xd7\x89\xf0\xce\x94\xdf\xb8\x1a\xe8\x91\x24\xe6\x0f\x8a\xb7\x57\x0d\xcc\xd1\x20\x1a\x0c\x68\x02\x18\xe4\xb6\x82\x41\x55\x03\x39\xf2\x04\x11\x60\x57\x38\xe4\x0a\x8d\x7d\x22\x0c\xc8\xe1\xa6\x8f\x40\xbf\xbd\x4a\x07\xe2\x3d\x3e\x6e\xac\xac\x69\x40\x79\x54\x54\x06\x95\xa2\x6c\xb3\x09\xfb\x56\x72\x57\x91\xd7\x46\xa6\x86\x82\x31\x8c\xaa\x51\x5f\xa4\x6f\x6e\x80\x78\xcd\xa0\x7a\x31\xaa\x93\x49\xb2\x16\xa9\x84\x23\xa8\xc5\x59\xee\xeb\x9d\x21\x9e\x31\x33\x38\x9e\x49\xfe\x12\xc0\xa9\x66\x88\x53\x4b\x50\xcb\xa8\xd5\xc2\x23\x73\xc4\xf6\xe4\x24\x69\x68\x05\x1a\x5f\x8b\xf4\xca\xf1\x5a\xe4\xb4\xe0\x4d\x9c\x18\xc3\x78\x27\x27\xfe\x76\x16\xe6\x9c\x53\x9c\x6f\x9d\x89\x95\xfb\xfc\x6c\xd4\x24\x93\x28\x4b\x4a\xf4\xaa\xc7\x09\xa1\xe4\xa8\x56\x21\xa1\x31\x23\x98\x95\x74\x6b\xbd\x3d\x41\x63\x23\xb2\xc7\x8b\x0c\x21\xb0\xc4\xa1\x7f\x48\xc6\xce\xf4\x31\x3c\xaa\x02\x6b\x96\x10\xf5\x75\x22\x60\x21\xc0\xfd\xc2\xd9\x75\xfe\x9c\x5d\x7f\x20\x34\x0f\x44\x03\xa6\x74\x0a\x4e\xd4\xed\x3a\xe1\x04\x7d\x78\xa1\x9f\x04\x0f\xbe\xd4\x81\xfa\x12\xee\x45\x64\xff\x3c\x61\xdf\x1b\x4a\x17\x69\x69\xe5\xf4\x37\x14\xca\x60\xcb\x47\x46\x0c\x4c\xeb\x3b\x71\xdf\x79\x52\x63\xfd\xcb\x87\xb7\xbf\x60\xf8\x84\x1a\x4e\xf6\x00\x2e\x85\x14\xcf\x3e\x35\x56\xb0\xd5\x3f\x06\xac\xac\x01\x57\xd7\x99\x06\xf0\x1c\x40\xb6\xc1\xb4\xed\x59\x74\x41\x22\x17\x11\x6f\x96\x8f\xbf\x7d\xab\xc8\x41\x90\x15\x20\xf5\x86\xc8\xb4\xb8\xc9\x67\xb7\x21\xbb\x8d\xc1\x09\xca\xfe\xb6\xce\x80\xfc\x61\x63\xaf\x4b\x3c\x0c\x61\x6d\xde\x5f\xb8\xce\x6b\x19\x2a\xba\x8e\x1f\x12\xb2\xde\x65\x51\xd5\xc1\x1a\x96\x64\xf7\xf0\x39\xbc\xa3\x28\x9e\x4d\xa4\xf9\x5d\xf8\x81\xd4\x61\x8c\x01\xde\xd1\x69\xcd\xc9\xc3\x44\xf4\x9f\x0c\x08\xff\xcf\x24\xb9\x42\x89\x55\x96\x04\x25\x30\x98\x27\xb2\x80\x4c\xa8\x83\xcf\x81\x40\x6c\x46\xe8\x44\x38\xee\x34\x12\x2b\xe7\x92\xb2\x40\x21\xba\x51\x34\x7f\x8a\x6e\x15\xcd\x00\x47\xa3\x5d\x83\xcb\xa0\x8f\x9d\xfd\x33\xf0\xb4\xb1\xb7\x02\xf4\xc9\x9d\x9f\x40\x15\xe6\x6a\x88\x4c\x90\xf3\x0b\xac\xbe\x53\x9b\x61\x4e\x1a\x83\xf3\xb7\x43\x3a\xc2\x61\xcc\xba\x5f\xea\xa5\x38\x3e\x86\x67\xbc\x97\x70\x59\x4e\x87\x31\xbf\xc9\x8c\x37\xb4\x60\x43\x6b\xb1\xe0\xd9\xfc\xe4\xc4\xf8\xe4\xc4\xf8\x24\x7b\xd6\xe0\xfb\xe6\x59\x06\x3f\xce\xf4\x2c\x6a\x7d\x08\xe6\x1b\x46\x50\xa6\xe4\x9f\x78\xf0\x7c\xb9\x5c\x13\x1a\x97\xcc\xb7\x12\x00\xb8\xf1\x5f\x34\x57\xef\x06\x80\x51\xdc\x3b\x86\x1e\x7c\x93\x62\x86\x9e\x29\x3c\xa1\x14\x08\x1e\x3f\xc3\xe3\xfb\x6c\x52\x56\x53\x01\x56\x6c\x27\xa1\x21\x8b\x7e\x13\x70\x21\x64\x45\xcb\x64\x6d\x66\x6a\xf4\xe7\x37\xb2\xf3\x83\xac\xac\xcc\xae\x1f\xcb\x70\x26\xe9\x64\x0a\xf3\xfc\xc1\xd2\x2d\x19\x95\x34\x4a\x90\xf1\xc9\x3b\xab\x22\xdd\xce\x11\x72\x3f\x48\xdb\x83\x4d\x84\x2c\xbe\x73\xa4\x17\x82\x39\xb4\x08\xfa\x79\x32\x87\xab\x11\x2d\x64\x51\xd9\x0e\xf8\x81\x18\x73\x11\x8b\x8d\x92\x31\x85\x73\x68\x4e\x88\x27\x62\xf7\xe4\xe2\xe7\xec\xf0\xc5\x9f\x17\x91\xe0\x16\x2f\xa3\xa9\xc5\x7c\xea\xec\x18\x24\x02\x46\x47\xad\x41\x0d\x48\x02\x6f\x1c\x4f\x7f\x9a\x8f\x6f\x77\x89\x6a\x79\xd1\xdb\x25\x9e\x9c\x2d\x63\xf0\x8e\x40\x84\x31\xf0\xbe\x43\x28\x40\xe8\xdd\x78\x46\x65\x0d\xeb\xf9\x62\xe1\x2c\xef\x9c\x2c\x02\xbc\x29\x4e\x90\x9a\x70\x47\x59\xfd\x4e\xa3\xf4\xaf\x9e\x94\x45\x78\x56\x0f\x47\x59\x78\x46\x59\xa1\xfd\x86\x3d\xca\x22\xca\x3d\xa3\x34\x52\x71\x00\x49\x35\x45\x1b\xd1\xaf\xdd\xe3\x4c\x68\x9c\x2a\x3d\x82\x68\x1d\x7a\xf3\x18\xc1\x95\xa1\x40\x7e\x2c\x9f\x41\x91\xb8\x01\x25\xbe\x99\x4a\x29\x44\x6b\x9e\x4d\xb2\xe0\x30\x15\xbe\x7e\x28\x01\x9b\x6a\x39\xc2\x49\xd7\x6c\x6d\x62\x41\x8f\xc0\x13\x4d\xdf\xdf\x31\x09\x2f\xbc\x27\xc2\x6c\x8c\x45\x1f\x97\x2a\x25\xb4\xd3\x08\x0a\x30\x3c\x86\x8d\x73\x69\xfe\xd2\x96\x89\xa8\xf1\xf5\xf7\x5d\x7e\x12\x63\xc0\x1e\xd8\x9b\xdb\xdd\x72\x94\x79\x61\x52\xe2\x0f\x21\x64\xb3\x16\x16\xaf\x1a\xda\x39\x96\xd3\x64\x7c\xc5\x89\x08\x8f\xb0\x34\x41\x40\x56\x36\xde\x6a\x27\x14\x8f\x84\xe8\x12\xac\xb3\xef\x28\x2f\x7d\x3b\xdb\x6c\x43\x2a\x88\x22\xad\xb5\xee\xc4\x88\x75\x6b\xf1\xf1\x40\x21\x44\xe0\x1d\x22\xf4\x83\xea\x1a\xe1\x70\x6a\x42\x8a\x25\xcc\x89\x3c\x08\x54\x88\x86\xac\xbe\xc8\xc4\x08\xf9\xdf\x50\x74\x0b\x83\x11\x17\x55\x37\xfe\xf1\x35\x94\xcc\x2f\x02\xc6\xe3\xc1\x65\xe8\x83\x35\xe3\x7e\xd8\x63\x0d\x78\x5c\x32\x4e\x8c\x35\x3e\x59\xa8\xc6\xe9\x9d\x2f\xca\x00\xa4\xd8\xcb\xb3\x4f\x8c\x86\x1a\xae\xd8\x3e\xc1\x76\x3d\xda\x0a\x38\x5d\x0a\xf0\xef\xef\xa7\xf4\x61\xfb\x04\x76\x7c\x28\x0e\x21\x77\x67\xe9\xd4\xeb\x48\xca\x05\xe3\xda\x52\x9b\x2c\xbf\x25\xd6\x81\x22\x59\xe2\xce\x44\x09\x8f\x77\xd9\x98\x1b\xf4\xaf\x9c\x0d\x91\x8d\xeb\x31\xba\xef\x12\x49\x62\x86\xe6\xdb\x66\x7a\xee\x77\xda\x42\x76\x75\x78\xfe\x43\x44\x99\xee\xd7\xc9\xe9\x10\xc8\x2d\x64\x7a\x16\x48\xd4\xa0\xdb\xa4\x59\x7d\x34\xc1\x38\x3b\x26\xbf\x31\xe9\xcb\x0c\xe0\xf9\xa1\xc4\x50\xc9\x07\xc1\x09\x56\xc4\xe1\x74\x80\xa3\x46\x66\x96\x29\xf1\x7a\xb0\x2e\xea\x79\x3e\x43\x10\x89\xa4\xff\xf3\xb3\x14\x83\x40\x8b\x34\x8b\x5d\xe3\x4d\x1c\x5e\xa5\xe6\x63\x03\x90\x6b\x0e\x8d\x17\x14\x3a\xa2\xe9\x5b\xc0\x8b\x8b\x8c\xdf\x28\xa7\x23\xf3\xbb\x35\x0e\x51\x0c\xe7\x14\xf3\x6d\xad\x4f\x4e\xfc\x9f\x2b\xbf\x24\x7f\xb7\xa7\xa7\xfe\xcf\x5c\xf0\xac\x34\x78\x56\x5b\xad\x9d\xdb\xee\x34\x5d\xf0\xb7\xcb\x26\xd9\x23\x2c\x63\x23\xf3\x44\x1a\x9e\x47\xec\x82\x25\xbd\x6c\x15\x23\x23\xc2\xab\x07\x7d\x25\x7c\x24\x7b\xf4\x11\xff\x61\x6f\x57\xf6\x07\x4d\x02\x1e\x37\x6a\x73\x24\x93\x5b\x9c\xe8\x26\x99\xf5\xfa\x1e\xd8\x9e\x64\xe6\xbb\x0c\x00\x15\xcf\xb7\x90\x97\x38\xd0\x29\x67\xa3\xf3\x1e\x15\x87\xb9\x48\x2d\xe6\x42\x68\x0c\x15\xe7\x20\x14\x85\x9a\xc7\x70\xad\x89\xb5\xea\xd0\x8d\xed\xa1\xda\xd8\xc6\xb0\x94\x82\x2f\x99\xc3\x93\xb8\x50\xa6\x18\xec\x59\xf0\x25\xf9\x94\xb9\x10\xa1\xb6\xa1\x67\x5c\x4e\x7e\x6a\x4a\xc1\xa3\x08\xc5\x4d\x80\x41\xec\x24\xe3\x42\x6c\x3a\x3d\x91\x33\x31\xa6\xfd\x43\x9e\xe7\xe0\x63\x3b\x71\x79\x8e\x85\xc5\x9e\x98\xd2\x0b\xa7\xe2\x8a\x42\x3c\x8a\x7c\x4c\x44\xf0\x14\xd3\x16\xc5\x54\x19\xf1\xf3\x69\x66\x24\xaa\xa2\x7c\x03\xa8\xe4\xb3\xf3\xd3\xa0\x28\xc8\x3a\x39\x33\x0f\x4e\x51\xd1\xce\x4a\xb4\xe4\x33\x60\xf0\xf8\x58\x70\xe0\xf8\xc3\x8a\xde\x45\x1c\xb8\xd2\xd4\x09\x8e\xbf\xdd\x93\x52\x12\xb6\x66\x41\xb6\x58\xf2\xca\xf3\xb2\x01\x28\xb9\xbb\x0b\x8f\x8a\xfb\xfb\xe2\xf8\x98\xac\x0a\xa4\x6a\x8d\x29\x39\x9f\x5b\x48\x23\x89\x38\x34\x53\x3e\x3e\xd6\x4b\x85\x41\x5c\xcd\xe0\x11\xc2\xd7\x02\x55\x2c\xe8\x19\xdd\xba\x93\x67\x84\xd2\x50\xff\xd2\x1a\x79\x4a\x79\xc5\x28\xd7\x74\x7f\x9c\xfa\xc8\x01\xa7\xdb\xa2\xab\x5b\x98\x1a\x92\x70\xf1\x41\xf5\xdb\xe3\xd4\x00\x65\xed\x2a\xe0\x82\x2d\x34\xce\xcc\xcf\xf4\x7a\xe7\x83\x58\x65\x07\xd3\x3b\x63\x64\x2c\xfc\xf0\x3a\xa8\x93\x99\x41\x64\x20\x55\x32\xdf\x68\x74\xdd\x96\xf6\xcd\x6c\xbb\x8c\xcf\xfb\x12\x18\x9d\xbe\x90\x8e\x26\xcb\x31\x06\xb2\xec\x8a\xf7\x21\x4c\x76\x79\x76\x58\x84\x89\x10\x96\x42\x9f\x15\x45\x5e\xc1\xcc\x0e\x74\xe9\x72\x1c\x16\x74\x41\x0a\x86\x4f\x56\x5f\x7b\x2f\x2b\x94\x0e\x7f\x48\x8b\xba\xf7\xa6\x2c\x4a\x40\x11\x3e\x17\xc3\xe4\xc9\x1f\x54\x53\xa6\xfc\x4e\x0a\x83\x17\x03\x63\x33\xc2\xb9\xbc\x07\xe6\xda\x62\x57\x96\xe9\xc8\x08\x78\x57\x8f\x81\x76\x69\x00\xc1\x4f\x06\xe8\x40\xab\x1a\x68\xa2\x69\xa4\xfa\x8b\xac\x91\xf4\x51\x6b\x8a\x01\x16\x0d\x69\x9f\xda\xc2\x94\xae\x93\x34\xaa\x23\x57\x5e\xb5\xc5\xf1\x4f\x18\x8e\xb8\x81\x9e\x76\x04\x49\xd7\xd5\xe7\xc9\xca\x50\x5e\xc3\xe5\x60\x1a\xf9\xf1\x0c\x3e\xef\x12\x4c\xc1\x96\x45\x39\x46\x37\xd4\x79\x17\xab\x68\x98\x3d\x6c\x4b\x93\xcc\x70\x3a\x4e\x92\xb1\xd6\x35\xa0\x83\x4b\x69\xc3\x56\xe7\x02\xf0\xdb\xb6\x12\xeb\xab\x1a\xb6\x4e\xf9\xd4\xb7\x5f\xe9\xb6\xfd\xb2\xce\x2d\x70\x7e\x91\x33\x28\x2b\xba\x12\x11\x9a\xee\x07\x3b\xec\x38\x31\xce\x90\xff\x43\x97\x5c\x2b\xf5\xf9\x2f\xb7\x1e\xf6\xd6\x99\xd6\x5e\x65\x06\xa8\xc0\x49\xfe\x21\x72\x20\xc5\xd2\x3c\x3b\x47\xf8\xc9\x2e\x27\x00\x0f\x6f\xd1\x9b\xec\x4d\x22\xed\x1d\xfb\xa5\x3b\x7c\x84\xe1\x92\x25\xe9\x9e\x85\xa6\x7b\x56\x87\xd3\x26\xa9\x0b\x71\x64\x4a\xa5\x00\xf3\xf9\x74\xea\x81\xca\x75\x27\xfd\x02\x57\xe7\x2a\x2b\x1c\x6c\x3f\x01\x70\x14\x62\xab\x26\x5a\xf8\xc5\x0e\x44\x77\x66\xad\x6b\x64\x82\x46\xc9\xa8\xfd\xd9\xd6\xa4\xaf\x41\xf3\xa6\x53\x84\x4a\xd6\xe6\xb5\x27\x1a\xde\x69\xae\x2e\x6f\x05\x14\x50\x17\xc9\x23\x1c\xfd\xbd\x21\x6e\x3a\x2f\x61\x18\xf8\x96\x4b\x78\x72\x08\x0b\xe3\xba\xd9\x74\xde\x73\x3b\xe2\x10\xfb\xd9\x6f\xe7\x64\x1c\x10\x63\x5f\x6d\xc2\xfa\x5b\x4e\x86\xe1\xd7\xad\x89\x78\xf4\x12\x46\x95\xba\xb0\x97\x89\x25\xc4\x6f\xf0\x84\x20\xb7\x52\xc3\x81\xf8\x06\xd8\x47\xd4\x25\xcd\x71\xac\x6d\x5a\x27\x6b\xa9\x46\x62\x87\xd9\xa8\xec\x10\x66\xae\x51\xe3\x48\xa1\xb3\x2d\x46\x57\x7e\x8f\x23\x0f\xa2\xa3\x35\x39\x3a\x7b\x3e\xdd\x7b\xb7\x27\x5b\xdc\x73\xb7\xec\xdb\x2e\x4b\x63\xdf\xbe\xdd\x08\x21\xc1\x8d\x0a\xbc\x3b\x0e\x97\xc9\xcd\xc5\x8d\xe2\xdc\x2f\x5b\x97\x3c\xa9\x0a\x97\xc9\x92\x67\xad\xad\x18\xfb\x42\x20\xcd\x41\x54\xa1\x4d\xb3\x95\x64\xe9\xa5\x12\x96\x4c\x25\x58\x70\x53\xbb\x70\xb3\xb6\x98\xce\x89\xc3\x74\xba\x9c\x24\x5b\x95\x7e\x93\xde\xcb\xef\xfa\x3a\xdd\x8a\xd0\x3f\x27\xb5\x86\x5d\x83\xf1\x6c\x7b\x6d\x92\x38\x0a\x35\x63\xa4\x9d\x8d\x6e\x50\xa6\x74\x9b\xa4\x87\x82\xf2\x62\x3b\xe7\xe8\xbc\x9c\x72\x72\x00\x99\x27\x74\xbb\xf6\x6c\x2b\x7b\x2a\xf4\x5a\x2c\x5a\xf4\x5f\x16\x2b\x43\xc1\xa6\x02\xc3\xee\xa5\x85\x73\xea\xcc\xbd\x59\x92\x24\xf5\xe1\x61\x60\x95\x95\x86\xce\x27\x3e\xbc\x1c\xe3\x8a\xc7\x66\xc9\x48\x2c\x7e\xe8\x4b\xfc\x49\x9b\x94\xdd\xdf\x4f\x88\xa7\x86\x1f\x6c\xe1\x77\xc3\x17\xd6\xd2\x39\xd1\x4b\x3f\x13\x95\xc1\x18\x96\xca\xb7\x4d\xdc\x27\xf2\x2a\x59\x2a\xe3\x45\xb4\xbd\x09\x51\x56\xdc\x3e\x47\x14\x88\xde\x3c\x4a\x7a\x3c\x59\xdf\x45\x49\xcb\x7e\xc7\xad\xd9\x58\xe3\xe0\x51\x29\xaf\x94\x6f\xe9\xbb\xf1\xf7\xdd\x71\xf7\xd9\xdd\x87\x6b\xa1\x08\x09\x6f\xcc\x0c\x9e\x91\x1c\x06\xed\x89\xaf\x75\x05\x6a\x2d\x4e\xdc\x98\x8d\xbd\xe4\xd8\xf3\x44\x49\x45\xb2\xbe\xd8\x84\xc2\xd6\xe9\xb7\xb7\xc4\x7e\x8f\x1b\x94\x93\x4c\xa5\x35\x26\x13\xb8\x3b\xe2\x6c\x8c\xd6\x5e\xd1\x80\xd2\xbb\x48\x8f\x48\x63\xd4\xa4\x35\x39\xb2\x76\x49\x00\x0f\xc5\x5d\x6f\x43\xd0\x18\xc6\xd7\x88\xf4\x14\x99\x31\xc2\xe8\x68\xd8\x8f\xf9\x38\x6c\xb6\xe8\x32\x78\xb0\x6b\x96\xa6\x34\xd1\x9d\xd0\x54\xc4\x72\x48\x78\x21\x1d\x1f\x1f\x99\x40\xa3\xc0\x85\x41\x43\xe6\xc6\x70\xd0\xbc\x67\xc5\x3c\xb9\xcd\x50\xc0\x9b\x98\x47\x83\x05\x4b\x06\xc8\x48\x34\xd9\x6e\x4e\xf9\x98\x78\x04\x07\x6a\xf8\x86\x56\xc5\x5b\x4d\x4c\x6b\x27\x5f\x72\xdb\xb6\xd1\xd5\x42\x33\xd1\x08\xd9\x7d\x4a\x9e\x3a\x47\xda\x93\x6c\xda\x46\xec\xfc\x85\xa6\x1e\xa3\x3e\xa9\xf3\x84\x95\xcc\x68\x6e\x58\x20\x3f\xd0\xe6\xcf\x27\xf8\x23\x13\xc1\xbe\x3a\xea\xc0\xb6\xe0\xdb\x33\x09\xe5\x82\xd5\xa5\x64\x45\xc7\xc7\x73\x5f\xd0\x83\x91\xa5\x01\x30\x18\x24\x57\x01\x40\xe8\x4e\x93\x21\xb7\xbf\x4b\xf2\x0b\xc7\x23\xbc\x2b\xec\xb5\xd7\xb6\xf8\x30\xa9\xcc\x93\x03\x3c\x69\xbe\x81\xa5\x73\xa4\xde\x9d\xe9\x67\x5d\x4a\xc4\x66\xdf\xda\x36\x34\x26\x6d\xf0\x0d\x5c\x5d\x4d\x3e\xa2\x2e\x06\xd6\x99\x6d\x2b\xf3\x90\xc5\x00\x0d\x15\x26\x57\x30\xac\xb6\xce\xa2\xaa\x8f\xa3\x9c\x08\x9d\x2a\x1e\xbb\x85\x18\x60\xd6\xca\xd8\xdc\xe2\x62\x74\x5a\xda\xe6\xb7\xb0\x42\x22\x6d\x6e\x37\xef\x97\xf9\x95\x18\x86\x0d\x44\xe3\xe5\xf8\x5a\x9a\x6c\xaf\x98\x53\x4d\x5f\xa9\x6c\x79\x19\x1a\x3f\x1b\x79\xd3\x1a\xad\x06\x28\x2d\xe8\xe4\x71\x09\x55\x2a\x19\x49\xed\xaa\x2f\xa2\x77\x7c\x3b\x63\xb8\xf3\x58\xed\x73\x8e\xf6\xb6\xcf\x97\x47\x62\x54\x0c\x3e\x7d\xfa\xe9\x65\xdb\x6c\x33\xf8\x2a\xfe\x77\x4a\xff\x3c\xc2\x7f\x6e\xe5\x4f\xf9\xbf\x40\x19\x3f\x3c\xb8\xf8\x7a\x7b\xf9\xe0\xc6\xe3\x93\x32\x7c\xf2\x87\x37\x69\x33\x1f\x54\x69\x31\x2d\x97\x40\x36\x9c\x61\x30\xd8\xaf\x80\x5f\x9b\x71\x16\x3f\x3c\xce\xee\x7f\xd0\x76\x33\x4d\xf9\x81\x70\x5a\x38\x7c\x42\xfe\x12\x85\x8e\x08\x95\xd8\x44\x0a\xe6\xfd\x11\x9a\x3a\x91\xf7\xa5\x02\x62\x7a\x8a\xe1\xdd\x42\x32\x9f\xfd\x53\xb9\xae\x6a\x38\xba\xc0\x65\x9f\x05\x98\xf7\xc5\x79\xff\x26\x2f\x00\xbd\xe9\x1a\x72\x10\xd9\x09\x1a\x4c\x16\xd8\xb7\x29\x9d\x6b\xd9\x3e\xf3\x52\x7a\xa8\xd7\x87\x97\xe3\xb3\xd8\xfc\xa9\x9d\x8b\xbf\xe4\xcd\xfc\x0d\x6c\x22\xed\xac\xa1\x33\xd1\x96\xd4\x65\x72\x86\x38\x8b\x2e\x85\x51\xfa\xac\x1c\x95\xd2\x6a\x1c\x70\x17\x69\x53\x4a\xc4\x56\xe1\x93\x93\xb0\x26\x21\xc6\x98\xff\x88\x7b\xfc\x64\x18\x9f\xf5\xfb\x7f\x28\xf0\x5e\x5b\x9f\x18\x31\x82\xe9\xed\x1f\x8a\xa7\x59\x3f\x97\x76\x1f\x25\x10\xf2\xa8\x31\x0b\x2e\xa3\x0b\x55\xf3\x92\x6f\x29\x91\x59\x5b\x37\x60\x25\xd6\x0e\x02\x40\x77\xc0\x02\xcd\x60\xb0\x73\x34\xea\x9e\x18\xc9\x5f\x6a\xa1\x83\x5a\x9f\x50\xfe\x6d\xd9\xf3\xb3\x04\x2d\x4e\x57\x4c\x91\x2f\x70\x0e\x67\x3a\x10\xf8\x14\x1a\x42\x33\x45\x61\x29\xff\xf9\xd9\x74\x34\x95\xf3\x5e\x02\x02\x9a\x5e\x8e\xe6\x64\x03\x77\x34\x8c\xd6\x27\x09\xc6\xe3\x3c\x49\x96\xaa\xed\x68\x76\x72\x12\xad\xa1\x87\x71\x88\x84\xd7\x6c\x6c\xf4\x33\x85\x82\xcf\xa7\xc3\x71\xb8\x48\x96\x27\x28\xb0\x87\xc5\xd3\xab\xd5\xc7\x8f\x13\x20\xbb\x56\x92\x55\xe8\xc7\xa1\x7a\xc6\x41\xe2\x24\x91\xc1\x44\x56\x5a\xb7\x75\x22\x1b\x3b\x49\x0a\xf8\x02\x7f\x47\xaa\xcf\xfe\xc6\xb7\xc6\x2b\xf4\xf6\xe8\x6f\x46\x7c\x69\x4d\xcb\x09\xc1\x87\xeb\x0e\x3b\x49\x8b\xcf\x69\x4d\x37\x19\x29\xcf\x5e\xb0\xd3\x49\x18\x9c\x4f\xe9\xb0\x1a\xea\x07\x27\x5f\xbd\xb4\x2e\x1b\xcc\xe0\x93\x24\x8b\x4a\xd8\xbb\xb4\x5e\x57\x19\x46\x44\x84\x33\xc3\xc1\xe4\x11\xac\x39\x4a\xfe\xb5\xd4\x69\x18\x47\x9f\xd5\x10\x5d\x63\x43\x37\x6e\x8a\xb8\x8f\x8e\xde\x83\xcf\x79\x9d\x5f\xe7\x00\x15\xb7\x49\x30\xcf\x81\xd2\x27\x3d\x37\xbf\xe3\xb8\xf5\xc1\xf0\xec\x6c\xf5\x35\x88\x54\x7b\xd7\xe5\xf4\x76\x90\xae\x56\x59\x31\xa5\x08\xf8\x30\x2a\x95\xb3\xc9\x0a\x86\x2f\x9a\x01\xb6\xa3\x9a\x2d\xca\x2f\x49\xc0\x43\x66\xfc\x55\xec\x18\x60\xd1\x1a\xc4\x3f\xe1\xc8\xcc\x7e\x8b\xfe\x48\x1a\xf7\x99\xfd\x6a\x39\x67\x8a\x7e\x3d\xbf\xb0\x75\x17\x72\x3f\x72\xb8\x51\x76\x5a\xa1\xcf\x8e\x76\x8a\x82\x1f\x9b\x08\x73\xba\x8f\xfe\x37\x5a\x6d\xca\x4e\xee\xb2\x05\x00" + +func bundle_js_gz_bytes() ([]byte, error) { + return bindata_read( + _bundle_js_gz, + "bundle.js.gz", + ) +} + +func bundle_js_gz() (*asset, error) { + bytes, err := bundle_js_gz_bytes() + if err != nil { + return nil, err + } + + info := bindata_file_info{name: "bundle.js.gz", size: 105000, mode: os.FileMode(436), modTime: time.Unix(1432518658, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _config_default_toml = "\x70\x6f\x72\x74\x20\x3d\x20\x31\x33\x33\x37" + +func config_default_toml_bytes() ([]byte, error) { + return bindata_read( + _config_default_toml, + "config.default.toml", + ) +} + +func config_default_toml() (*asset, error) { + bytes, err := config_default_toml_bytes() + if err != nil { + return nil, err + } + + info := bindata_file_info{name: "config.default.toml", size: 11, mode: os.FileMode(436), modTime: time.Unix(1432518635, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _font_fontello_eot_gz = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\xe5\x57\x6b\x6c\x5b\xd7\x7d\x3f\xe7\x5e\xf2\x92\xa2\x1e\xa4\x2c\x89\x92\x45\x99\x3e\xd4\xb5\x28\x59\xbc\xa4\x64\xea\x69\x59\x66\x14\x52\x0f\xc7\xb2\x1d\x5a\x56\x3c\xd2\x49\x13\x52\x14\xf5\x70\xf4\xe0\xf4\x30\x94\x07\x82\x60\x4d\x87\x4c\xc8\x32\x23\x28\x8c\x61\xcd\x80\xae\x70\x8a\xa2\x9f\x0e\x9d\x74\x49\x87\x00\x29\x86\xb5\x68\x87\x06\xd8\xb0\xa0\xd8\x87\x3d\xfa\xa1\x1f\x54\xac\x43\x3f\x6c\x2b\x30\x60\x91\xf6\xfb\xdf\x7b\x25\xcb\xb2\xbc\x01\xc5\xbe\x8d\x14\xcf\xff\x71\x7e\xf7\xfc\xff\xe7\xff\x38\xf7\xe8\xbf\x9a\x18\x9b\xc6\x8f\x33\x85\xd1\x47\x61\x4e\xd5\x64\xa0\xb9\xcb\x89\x5e\x49\xb3\x23\x1f\x6e\xd3\x9e\x6f\x2c\x7c\x7e\x74\x8e\x31\x1f\x9b\x63\xab\x6c\x85\x6d\xb0\x22\x5b\xc2\x77\x15\xba\x1a\x36\x05\x69\x9e\x6d\x42\xce\xb3\x35\x68\xfc\xec\x26\x34\x6b\x6c\x9d\x2d\x9a\x68\xc1\xce\xb1\x18\xeb\x7e\xc2\xf3\xb6\xd1\x1a\xf6\x26\x53\x59\xee\xd9\x1b\x5d\xf1\x44\xc7\xa5\x7f\x83\xe6\x57\xf8\xdd\x2c\x2c\xe7\x4b\x7f\x73\xf2\xe4\xc7\x00\x8d\xe2\x77\xb9\x70\x67\x43\x58\x0f\x55\xbd\x80\xc1\x33\x57\x9a\x5f\x7e\xfb\xee\xdd\x2c\xe4\x05\xc6\x2a\x4b\xf3\xf9\xf5\x92\x69\x88\x55\x4d\x83\xba\xe7\x97\x5e\x99\xfb\x4d\xfd\xfb\x03\xd8\xfd\x5d\xc6\x9c\x3f\x5e\x28\xe6\x67\xb5\xc1\xa9\x5a\x4c\x65\x30\xdf\xbf\x00\x85\xeb\x9f\xd5\x6f\x41\xc6\x3c\x3b\xb3\xb0\xbc\xb1\x15\xfa\x3a\xad\xef\xfe\x08\x43\xc7\xd2\x6a\x21\x5f\xd1\xe4\x32\x20\xff\x03\x6d\x6d\x39\xbf\x55\x62\xdf\xae\xfc\x17\xc8\xff\x0e\x59\xac\xe4\x97\x8b\x3f\xfd\xd3\xc0\x29\xc6\x2a\xea\x61\xe3\xf3\xd2\xea\xfa\xc6\x77\x7f\x3e\x79\x1e\xbe\xfc\x02\xf3\xab\xa5\xb5\x62\xe9\x1f\x5f\x56\xbf\xc6\x58\xe3\xdf\x43\x7e\x8d\x71\xf5\x05\x7e\x97\x39\x99\x5b\x79\x55\xf9\x14\x9a\x77\x2c\xca\x7f\xce\xce\x71\xe5\x70\x8e\x8e\x7e\xd2\x73\x63\xb3\x6c\x64\x87\xed\xb8\xd5\xa9\xbd\xdb\xec\x96\x3a\xc5\xee\x1d\x4a\x18\x63\xaa\xfd\x6b\xb1\x75\xa3\x90\xb8\x29\x3b\x58\x07\xa8\x06\x6a\x96\xc2\x8e\x7b\x6f\x8f\x00\x3b\x8c\x68\x13\x7f\xb8\x06\xd7\x8e\xb7\xfd\xff\xec\x83\x18\xed\x95\xd5\x5b\xaa\x87\xb9\xd9\x02\x73\x7f\xef\xba\xd0\x14\x25\x1a\xe1\xbd\xe1\xd6\x1a\xee\x8f\xf7\xb7\x35\xd4\x6b\x5e\xae\xb9\xfc\x8d\xfe\x7a\x57\x0d\x6f\x6f\xed\x82\x80\x6f\x84\xb7\x86\xfb\xda\xc3\xed\x2e\xad\x15\x63\xb8\x77\x20\xc1\x07\xc2\x5d\x3c\xc6\xdb\xfb\x7a\xfb\x9f\xe2\xfd\x03\xb6\xb2\x27\x7e\x1a\x02\xbe\x17\x78\xdc\x7f\x9a\xfb\x1b\x07\xfa\xe3\x8d\xb4\x98\x97\x43\x0c\x72\xe5\xc2\xd4\xd6\x94\x72\x73\xe3\x26\x6f\x71\xbb\x16\x3c\x95\x75\x1d\x9a\xd3\x9b\xae\x76\xb9\xae\x9e\x6c\xae\x70\x39\x7c\xaf\xbb\xab\x7c\x81\xc6\x67\x35\x9f\x36\xee\x77\x38\xdd\x1d\x1e\xaf\x7b\xce\xe5\xe6\x1e\xe7\x82\xbb\xa6\xb1\xcd\xc2\xba\xaf\x36\x35\x57\xb8\xd5\xda\xd7\x5d\x55\xdc\xdb\xe2\x4f\x3b\xbd\xae\x4b\xf5\x0e\xc7\x85\x9a\x8a\x39\x97\x87\xbf\x78\x61\x7a\xfa\xce\xf4\xf4\x16\xcd\xfa\x82\x0d\x81\xb8\x56\xa3\x35\xa4\xb9\x73\xb8\xda\x7d\xa5\xc5\xe7\x71\xcd\x57\x54\x0d\x3b\xb5\x91\xa0\xb3\x46\xab\x8a\x7b\x5b\x02\x5e\x5e\xe5\x32\xb1\x27\x9b\x45\xd4\x55\xe5\xaa\x4f\x5b\x50\xaf\xdb\x6d\x42\x9d\xa9\x16\x40\xaf\x9a\x40\xab\x0a\x99\x7a\x82\xff\x2b\xf3\xb2\xd3\xac\x8b\x79\x3e\x36\xf4\x96\xba\x2a\x55\x8d\x46\xea\x10\xba\x76\xbd\x35\x4c\x11\x19\xe8\x89\xfb\x9d\xb6\x3c\x70\x44\xbe\xc8\x2d\xf9\x67\xc1\xc6\x97\x1b\x83\x5c\xf8\x5f\xf6\x0b\x7e\xca\x22\x96\xea\xb4\x29\x58\x9a\x8f\x1f\xaa\x0f\x43\x1e\xe1\x29\xaf\x7b\x7b\x7b\xb7\xd5\x3f\x53\xab\x91\xd7\x10\xf2\x7a\xb2\x52\x53\xcd\xbc\xc6\xb8\x16\xe4\x09\xce\xeb\x35\x4a\xa5\xde\x1a\x53\x12\x8e\xa0\xd2\x58\xef\x6a\xf4\x2b\x5f\xfd\xfa\x4f\xef\x39\xde\xfd\xe2\x1d\xde\x6a\x0c\xd5\x7f\x36\xfb\x5a\xfa\xbd\x85\x11\x65\x78\xe9\xdd\xfb\xef\x94\x06\xd5\xb1\xcf\x1a\xf8\xef\xcd\xbf\xa7\xdc\xfb\xeb\x3f\xd6\xde\xd9\xfd\x93\x53\x9d\x0d\x9f\x8d\x25\x6e\xdf\xfd\xd6\xbb\x2b\x43\x8e\xe4\xdc\xbd\xab\xaf\xcd\x7e\xd6\xb0\x5f\x4f\x75\x6a\x15\xa2\xd1\x01\xbb\x28\x23\xaa\xa7\xb6\x7a\x4d\x0f\xa1\x62\x7a\x13\xce\xc6\x78\x50\x89\x27\x94\x9e\x78\xd0\xa9\xc2\x89\x70\x02\x55\xa0\x9e\x98\x4a\xed\x36\xa5\xa6\x1c\x55\x27\x82\xe1\xa1\x90\x33\x6c\x5c\xb9\x7c\xb9\xbb\xd5\xd5\x3a\xd8\xd1\x52\xef\xd1\x3e\x7a\x43\xbe\xe9\xd8\xfa\xe4\x4e\x32\x75\xed\x5a\x2a\x38\x98\xec\x1f\x6c\x6d\x56\x9a\x82\x4d\xf8\xf3\x87\x7b\x87\x12\xc3\xfc\x67\x99\x37\x80\x51\x5e\x67\x1a\xed\xdb\xd1\x85\x13\xa3\x96\xc5\xd9\x05\x9c\x0c\x37\xd9\x4b\xac\x76\xa4\xe6\x2b\xd9\xe9\x89\x54\xe2\x7c\x9f\xa8\x77\x29\x1a\x02\xa1\xb9\x28\x15\xbd\x70\x83\x0f\xc4\x07\xb4\x86\x7a\x6e\xb9\xd8\x0e\x17\xa1\x54\x12\x9c\xaa\x38\x1e\x74\x34\x52\xa8\xc2\xbd\xfd\x71\x3f\x98\x18\x4f\x28\x7e\x27\xe5\x2d\xdc\xde\xdf\xd7\xdb\xee\xef\x89\x27\x78\x63\xbc\xfd\x00\x32\x79\x6b\x68\x32\x3a\xc2\xc7\x1c\x9d\xc9\x50\xb8\x4d\x55\xbe\x4a\x1b\x1b\x4d\x73\x47\x95\x4f\x60\x67\xda\x99\xd8\xa5\xf4\xf8\xc9\xb3\x3e\x97\x3e\x18\x16\xbe\x1a\xfe\xe5\x8f\xa8\x38\xef\x4c\xf3\x3f\x30\xfd\xff\xe8\x55\x9e\x4a\xc4\x26\xcf\xdf\x8a\xaa\x6d\x6d\xa1\xd1\x0e\xc7\xd8\x84\x3d\xff\xa2\x3a\x6a\x18\x3f\xf4\x37\xf3\xea\x06\xdf\xb5\xdd\xe7\x93\xd7\xae\x25\x11\x89\xc1\xde\xb0\xbf\xa9\xa5\x59\xf1\xfb\x9a\x3d\x0a\x62\x31\x98\x6c\x51\xfe\xc8\x2a\xf8\xdd\x5f\x67\xdf\x50\x5e\xfd\xf3\x2d\xed\xad\xbf\x8b\xc4\xf8\xa8\xfa\xf4\x35\x5f\x43\x75\x53\x13\xb7\xa7\xed\xde\x7f\x5f\x7d\x4b\x15\xac\x91\x05\x91\xab\xe0\xc9\x6a\x27\x72\x15\xea\xeb\x69\xb0\xd3\x55\xdb\xdb\xdf\x13\x8a\xfb\x4f\x71\xbd\x2f\x54\xcb\x5d\x7d\x21\x7c\xf9\x6f\x66\x86\x3a\x77\x4b\x1d\xc3\xc3\x1d\xfc\x6e\xe7\xd0\xcc\xee\x8a\x2a\x7e\xb4\x9b\xe0\x7f\x39\x3b\x4b\x3a\xe5\xd3\xce\xa1\xa1\xce\x7b\xf7\xbe\x1c\xe5\xe3\x7f\xb5\x75\x6f\x8b\xd9\x3d\xa2\x7c\xaa\x64\x58\x25\x2c\xe9\xe8\x91\x96\x26\x5f\x95\x83\xa1\x47\x70\x28\x58\xa6\x60\xa8\xcf\x1c\x43\xa6\xa6\xf6\x90\x5e\xd9\xf6\xb7\x04\xeb\xbf\xfc\x4e\x7d\xb0\xc5\x4f\x3f\x25\x43\xf2\x43\x1d\xbf\x1b\xec\x08\xe2\x6f\xd6\x22\xbb\x5f\x58\xd4\x7c\x5f\xec\xfd\xa7\x7a\x42\xad\x84\x4d\xed\xc3\xe6\x0a\x0e\x7b\x66\xcf\x61\x30\xb3\xdf\x77\xd0\x9d\x18\xe8\x80\x6a\x6c\x40\x1f\xaa\x27\x84\x7f\xc7\xea\xa7\x1d\xb3\xb3\x76\xac\xb6\xda\xd9\xef\xbe\x5f\xfa\xa1\x6d\xf8\xe5\x81\x96\xe0\xb4\x45\xb2\xf7\x6b\xe5\x0b\xe5\xf7\xd9\x19\xd8\xf3\x3b\x38\xd5\x3d\x0e\x4f\x34\x9a\x8b\x86\x70\xef\x53\xbc\x9d\x86\x7e\x1c\x8a\x03\x34\xd0\x31\x88\xbe\xfb\xc2\x7b\xc5\x67\xf8\xee\xdf\xc7\x70\xc5\x47\xd4\xf7\x50\xf6\x7a\xef\xdf\xf7\x96\xfc\xc4\x7c\xf0\x81\xf7\x71\xa0\x37\x46\x00\xf3\xbd\x86\xdf\xe7\x0b\xdf\xe8\x79\xc9\x3b\xfc\x1f\xac\x52\xdd\x21\x97\xfe\x76\xf3\xfd\xb4\x45\xd7\xc4\x41\x67\xe0\x85\x6e\x5f\x93\xcc\x67\xac\x77\xac\xa3\x0b\xde\xef\x3a\xba\x0f\xbd\x65\xad\x8f\x87\x56\x52\x71\xeb\x50\x71\x93\x50\xbf\x69\x51\x42\xab\x6f\x51\x56\x6d\x7d\xad\x8d\xfe\x26\xfb\x15\xef\xe0\x0b\x7c\x57\x89\x2b\x2b\xca\xb7\x95\x5f\x58\x36\x98\x07\x17\x24\x6d\xff\x8d\x83\x3b\xcb\x3a\xc6\xd6\xca\x92\xfd\xd4\x09\xf6\x4f\x07\x76\xfb\xd8\xfe\x9b\x9e\xc3\xcf\x3e\x9b\x57\x98\x8b\x5d\xb4\x79\x15\xfa\x51\x9b\x77\x80\xbf\x62\xf3\x4e\xd4\xd7\xb4\xcd\x6b\xd0\xbf\x64\xf3\x1e\x16\xc1\xa5\xcd\xe2\x2b\x59\x1d\x7b\x8f\x6e\x0b\x8e\x0a\x48\xb7\xd9\x07\x36\xcf\x99\x8f\x7b\x6d\x5e\x61\x35\xfc\xb4\xcd\xab\xd0\x47\x6d\xde\x01\xfe\xa2\xcd\x3b\x99\x9f\x5f\xb5\x79\x0d\xfa\x82\xcd\x7b\xd8\x4d\xbe\x6e\xf3\x95\x2c\xcc\x7f\x92\x5a\x2d\xbd\xb2\xb6\x38\xbf\xb0\x21\x3a\x52\x67\x45\xbc\xfb\x5c\x9f\x98\x79\x45\xac\x42\xb5\xb8\x92\x5f\x12\xf9\xcd\x8d\x85\xd5\xb5\x75\x31\x22\xe6\x56\x57\x36\x8a\x4b\x4b\xab\xb1\xc2\xea\xf2\x3e\x3f\x55\x9c\xdf\x5c\xca\xaf\xed\x8b\xfb\xf4\x66\x71\x6d\x7d\x71\x75\x45\x9c\x8b\x75\xef\xab\x26\x8a\x2b\xc5\xb5\xfc\x46\x71\x96\x56\x5f\xbf\x33\x1f\xdf\xd8\x98\x13\x73\x6b\xab\xcb\x62\xdc\x46\x88\xd2\xda\xea\xed\x62\x61\x23\xb6\xb0\xb1\x51\x1a\xea\xea\x3a\x6c\x8f\xa5\x70\x3f\x2d\xb1\x57\x70\x93\x5d\x44\xa8\x16\x70\x6b\x15\x38\xbe\x53\xec\x2c\x68\x1c\xf7\xd9\x73\x48\x84\x60\x33\x40\x08\x20\x2d\xd4\x22\x6e\xb7\x79\xdc\x6c\x05\xc6\x4d\x3c\xb1\x60\xce\xac\x43\x1e\xc1\xef\xe8\xed\x37\xc6\x0a\x18\x97\x1f\xd3\x3f\x7a\xa3\x3e\x3a\x7b\x54\x3e\xfe\xb6\x7d\x14\x35\x01\x6e\xc5\x44\xe6\x4d\xed\xec\x81\xef\xeb\xec\x0e\xac\xc5\xa1\xdd\xc0\x53\xe4\xe5\x9a\xe9\x95\x60\xe3\x47\xd6\x10\x88\x07\xcd\xdd\x86\xa6\x00\x7d\xcc\x8c\xca\x06\xb4\x43\x78\xcd\x77\x3d\x71\x7f\x76\x85\x5b\x75\x77\xfc\x07\x7a\xae\x70\x95\x3b\xb8\x93\x6b\xdc\xc5\xdd\xbc\x82\x7b\xd4\xc2\xea\xbc\x1b\xf9\x58\x2c\xad\x2f\xae\x6b\xeb\xc5\xfc\x5a\x61\xc1\xb1\xb9\x5e\x5c\x73\xd2\xb0\xae\x2d\xad\xce\xaf\x6e\x6e\x38\x96\x8b\x2b\x9b\x8e\xd2\xd2\xe6\xba\x56\xc8\xaf\x14\x8a\x4b\x56\x9f\x70\xdc\x6e\xbd\x87\x4d\x48\x66\x08\xc9\x9e\xcb\x8c\x65\x85\x98\xfc\x84\xd5\x5c\x9f\x94\xda\x8d\x5b\x19\xd9\x1b\x90\x1d\xd9\xdc\x9c\xd8\x7e\x2e\x23\x95\xb6\xfc\xf7\xdd\x68\x93\x42\x41\x9f\x09\x84\x42\x92\x65\x25\x4b\xe9\xa3\x0f\xb0\x5e\x2a\x97\x8c\x4a\x6e\x48\x91\x9b\x8b\x4a\xc5\x10\xb3\x42\xfe\x20\x2d\x1d\xe1\x5b\x0f\x3a\xb8\x27\x35\x56\x18\x9b\x7a\x3e\x13\xd2\x43\x81\xed\x8c\x90\xe9\x74\x26\x24\x47\xb2\x01\x21\x07\x89\x1b\xcc\x66\x45\xd9\x02\xe5\x67\x65\x07\x54\xb6\x24\x64\x37\xcd\x77\x13\xf2\x07\xe9\x8c\x80\x13\xdb\x79\x21\x3d\xe9\x4c\x0e\x1a\x41\x73\x1e\xe2\xfa\x89\xeb\xcf\x05\x72\xd9\x6c\x36\x20\x79\x24\x9b\xd5\x25\x4b\x67\x8a\xd9\x6c\x54\xaa\x86\xc0\x3a\x8e\xb6\x3c\x1c\x72\xa6\xd2\x19\xe9\xd4\x93\x52\xd3\x93\x70\x3f\x2b\x79\x2e\x2a\x1d\x86\x0e\xbf\xc4\x6c\xd9\x39\x93\x14\x34\x63\x19\xa7\x51\xb2\xdc\x58\x41\xaa\x9d\x21\xe8\x53\x62\x5b\x6c\x63\xed\x72\xb7\xb3\x0d\xdb\xba\x9e\xc9\xa5\x03\xf9\xa9\x6c\x46\xcf\x62\x76\xe4\x46\x06\x53\x01\xda\x94\x6d\x39\x2a\x9d\x86\x74\xa5\x22\x0f\x90\x5a\x33\x34\x1a\x44\x3d\xa9\x23\xc4\x7a\x32\x2f\x95\x99\x39\xc9\x0b\xb0\x2f\x9d\x9d\x51\xe9\x32\x04\x39\x59\x99\x2a\x7c\xe2\x60\x33\x82\x56\x90\x23\xb9\x2c\x41\x72\xa3\xa6\x93\x6e\xe3\x81\xab\x92\xa5\xc6\x92\x9d\xa1\x83\x60\x57\x18\x8f\x06\xdf\x63\xad\xc2\x23\x70\x21\x85\x1d\xe7\xc4\xd8\xb6\x9e\xa7\x44\x98\x91\x62\x01\x8a\xa6\x14\x01\x38\xb9\xef\xa5\x54\xdb\xf4\xfc\xa8\x65\xa2\xf2\x09\x8f\xcb\x33\x78\x8a\x05\x1e\x6e\xed\xf0\x43\x55\x86\xb9\xa1\x07\x95\x1e\x75\x2c\x13\x0a\xe8\xa1\x6c\x67\x28\x2a\xab\x8d\xb2\xa2\x8c\xc9\xd9\xfc\x68\x54\xd6\x18\x00\x0a\x21\xab\x52\x97\xe9\x71\x30\x7a\x32\x2b\xab\x49\x9a\x82\x54\x0d\x29\x2a\xbd\x58\xc6\x67\x86\x44\x20\x02\x05\xd8\x95\x35\xa9\x9c\xd8\xce\x09\x59\x83\xa0\x45\xa5\xcf\x98\x9c\xce\x94\x1d\xb3\xa3\xd9\x33\xb2\xba\xa8\x6f\x45\x65\xad\x31\x79\x3d\x33\x79\xc3\x52\x06\x42\xd0\xd7\x99\xfa\x13\x46\x99\x79\x53\xcf\x65\xca\x5e\x6f\x4a\xf2\x7c\x52\x7a\x23\x54\xa4\x28\xdd\x64\xb9\x8a\x86\x6a\x0c\x92\xfb\x91\x09\xb5\x2d\x9d\x29\x53\xf0\xb0\xdb\xe4\x36\xd2\x4b\x66\x3b\x43\x3a\x1e\xdb\xe7\x03\xd6\x3c\x3d\x82\xda\x27\x4d\x16\x3b\x99\x80\xff\x13\xd0\x3e\x9a\xaa\x27\x24\xb0\xcc\x58\x9d\x8e\x68\xa1\x9a\x12\x0f\x38\xe7\x66\xae\xea\x0c\x56\x66\xca\xd8\x74\x46\x7a\xf5\xa4\x18\x93\x95\x28\x4a\x0f\xe2\x9b\x4b\x8a\x1c\xcc\x7f\xcf\xe7\xe3\xf8\x9f\x3f\x99\xdc\xce\x95\x4f\x68\x11\xb9\x16\x09\xb4\x22\x4c\xf5\xd8\x5b\x5d\x24\x2a\x1b\x8c\x32\x27\xea\x47\x9c\x89\x36\x1a\xb8\x3f\x83\x36\x19\x65\x07\xd1\x93\x46\xd9\x49\xb4\xd9\x28\x6b\x44\x03\x46\xd9\x45\xb4\xc5\x28\xbb\x89\x9e\x32\xca\x15\x44\x83\x06\x93\xd5\x91\xdf\xc2\x91\xd3\x70\x24\x88\x05\x04\x1c\x21\x1a\x82\x23\x44\x5b\xe1\x08\x51\x1d\x8e\x10\x3d\x03\x47\x88\xb6\xc1\x11\xa2\x61\x38\x42\xb4\x1d\x8e\x10\xed\x80\x23\x44\xcf\x1a\x62\xd8\xac\xa7\x4e\x03\x66\x7d\x39\x91\x42\x12\x72\x29\x33\xe6\xe8\x91\xb3\x54\x54\x11\x43\x76\x46\x64\x27\xda\xc5\x40\xa5\x4e\x88\x27\x84\x5b\xcf\x0f\xea\x74\x56\xfd\x8f\x08\xd4\x4b\x54\x46\x0f\x72\xc0\xfd\xd2\xe8\x94\xbc\xa1\xdb\xdc\x5c\xec\x70\x54\x1e\x9d\xea\x32\x44\x9f\xe9\x67\x37\x30\x7c\xec\xf1\xc5\xd1\x3e\xc7\x1a\x25\x3d\xf3\x7f\x64\x1e\xb4\xa3\x09\x7d\xb0\xdc\xc5\x1b\xb0\x93\x73\xd8\x37\x1c\x3d\xde\x4f\x54\x6d\x7e\x30\x2a\xe3\x46\xac\x71\x38\x2a\x7b\xfe\x37\x28\x2a\xac\x00\x78\x2f\x52\xc1\xfc\x6d\x22\x26\x26\xa8\x33\x11\xc2\x67\xb6\xb7\x27\xf4\x09\xb4\x72\x06\x67\x36\xce\x3c\xb4\x6b\x0f\xc7\xad\x16\xf6\xfb\x70\x84\xf8\x51\xfd\xf8\x33\x21\xb2\x22\x15\x29\x6e\xc7\x74\x21\x86\xb7\xb1\x56\xff\xc3\x69\x11\xb3\xd6\x90\x0e\xac\x09\x94\x90\x39\x6a\xe6\x91\xeb\x99\x0f\x15\xa1\x8a\xc0\x87\x4a\x58\x6d\xce\x26\xe9\x80\x73\xe3\xa8\xd4\x4d\xb4\x3e\x8e\xd6\x4a\x1d\xed\x93\x1c\x1d\x32\xd6\x49\xae\xa4\x72\xb3\xba\x54\x53\xf9\x59\x4c\x2b\xa9\x7c\x00\x7c\x8e\x0e\x98\xa3\xcf\xe4\xe1\x12\x4e\x5d\x7d\x1c\xb9\xd3\x61\x61\x1c\xfb\x02\x31\xad\x60\xbd\x63\x8c\xe8\xd6\x51\xe6\x40\xf7\x22\xf6\x4e\x14\x92\xf3\xb1\x55\xb1\x22\xed\xa8\xcd\x74\x02\x63\xda\x3a\xc2\x1e\xda\x42\xca\x07\x28\x06\x02\x1a\x67\xd8\x8e\x81\x3e\x8c\xd0\x0c\x9a\x6a\xe9\x46\xd3\x08\x31\xae\x4f\x90\x31\xca\xd6\x79\x33\x64\xb4\x01\x3b\xa2\x6c\x3a\x13\x13\xc3\x78\xf1\x91\xc7\xb6\x52\x90\x2f\xfb\x21\xd7\xda\x20\x3d\x73\xf8\xd5\x6a\x25\xea\xb8\xca\xb5\x33\xa3\x53\xf9\x0e\xd9\x1e\xa4\xf6\x53\x93\xa3\x77\xef\xd1\x2d\xee\xa7\xf2\x82\xa1\x8b\x18\x45\x6d\x1c\xa7\xee\x70\x36\x56\x8e\xf0\x7a\x34\xde\xf0\x81\x3a\x7d\x58\x7d\xf1\x51\xf4\xb1\x98\x84\x21\xfb\x22\xc7\x2e\xfa\x94\x21\xfb\x23\xdb\x30\x4c\xc5\x02\x6f\x1f\xc7\x20\x2d\x31\x19\x01\x74\xe4\xa0\xc2\xf6\xa3\x4b\xc5\xa5\xa3\xd4\x63\x68\x12\x6b\xb9\xa7\x71\x58\xe0\x80\xfe\x2d\x4a\x71\xe2\xff\xaa\xfa\xc8\x7d\x3a\x57\x86\x75\x1c\x1d\x87\xf2\x1d\xca\xda\x3e\x26\x29\x18\xfb\xfb\x4f\xd1\xfe\x43\xba\x1d\x00\x7b\x1f\x07\x5b\x1e\xc5\x96\x1b\xac\xe6\xc4\xab\x1b\x7d\x58\x17\x93\xe7\xd0\x8b\x63\x4f\xd0\x8f\xe3\xac\xe5\xf5\x75\x32\x0e\x7e\xc2\x90\xbd\x20\x97\x28\x6a\x63\x88\xab\x18\xc7\x7b\x6a\x3f\x4e\xcf\x18\x54\x8e\xf2\x12\xd8\xcb\xc6\x03\xc6\x9e\x06\x33\x09\x86\x13\x73\xc5\x78\xc0\x4d\xcd\x55\x30\xa6\xe6\x1a\x61\x92\x60\x9e\x25\x0c\x31\x69\xc2\x10\x73\x9d\x30\xc4\x4c\x11\x26\x01\xe6\x06\x61\x88\x99\x26\x0c\x31\xcf\x11\x86\x98\x9b\x84\x19\x01\xf3\x3b\x84\x21\x26\x43\x18\x62\xb2\x84\x21\xe6\x16\x61\x52\x60\x9e\x27\x0c\x31\x2f\x10\x86\x98\xaf\x10\x86\x98\x17\x09\xf3\x14\x98\x97\x08\x43\x4c\x8e\x30\xc4\xe4\x09\x43\xcc\x8c\x21\x07\x0e\xc2\x5c\x20\x41\x5e\x00\x37\x6b\x72\xc3\xe0\x8a\x66\x3d\x41\xb8\x08\x61\xce\x90\x83\x07\xe8\x79\x12\x4c\xf4\x82\xc9\x11\x7a\xd1\xe4\x08\x7a\xdb\x90\xe7\x0f\xa0\x2f\x93\x60\x42\x97\x4c\x8e\xa0\xcb\x26\x47\xd0\x15\x43\x0e\x1d\x40\x57\x49\x30\xa1\x25\x93\x23\xe8\xef\x9a\x1c\x41\xd7\x8c\x0f\x2b\x1c\xca\xfe\xcd\x28\x19\x91\xee\xa2\x54\xcf\xa4\xb7\xe8\x7d\x12\x65\xb8\x64\xff\x78\x0a\x17\x10\xfe\x2e\x0e\x65\xab\xf7\x4b\x65\xe6\x4c\xe2\xc2\xd0\x69\x51\xf7\x23\xf4\xfb\x78\x77\x54\x1c\xe6\x54\x36\x5a\x3e\xc3\xdf\xbe\x8e\x3a\x7d\x3b\x53\x56\x67\x47\xcb\x61\x92\xfe\xc2\xfd\x26\xfe\x97\x1c\x79\xbb\x80\x1b\x13\x20\xb8\x13\x67\xcb\xac\xaa\xf3\x13\xbe\xf7\x35\xe9\xf8\x43\xbc\x1d\x46\xd9\x7f\x03\xf9\xb4\x1b\xf4\xfc\x18\x00\x00" + +func font_fontello_eot_gz_bytes() ([]byte, error) { + return bindata_read( + _font_fontello_eot_gz, + "font/fontello.eot.gz", + ) +} + +func font_fontello_eot_gz() (*asset, error) { + bytes, err := font_fontello_eot_gz_bytes() + if err != nil { + return nil, err + } + + info := bindata_file_info{name: "font/fontello.eot.gz", size: 3543, mode: os.FileMode(436), modTime: time.Unix(1432518658, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _font_fontello_svg_gz = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\xad\x57\x6d\x8f\x1b\x35\x10\xfe\xce\xaf\x18\x82\x84\xe0\x83\x13\xbf\xac\x5f\x16\xee\x5a\xc4\xb5\xaa\x90\x10\x54\xa2\x80\xf8\x18\x92\xed\x25\xd2\x26\xb9\x24\xbe\xbb\xb6\xbf\x9e\xe7\xb1\x37\xed\x35\xb9\x83\x83\x22\x25\x6b\xaf\x3d\x6f\x7e\x66\x3c\x33\x7b\xf6\xf4\xcd\xaa\x97\x9b\x6e\xb7\x5f\x6e\xd6\xe7\x23\x33\xd6\x23\xd9\xe7\xe9\x7a\x3e\xed\x37\xeb\xee\x7c\xb4\xde\x8c\x9e\x3e\xf9\xec\xec\xf3\x67\x3f\x5f\xbc\xfa\xe3\xe5\x73\xd9\xdf\x5c\xca\xcb\x5f\xbf\xff\xf1\x87\x0b\x19\xa9\xc9\xe4\x77\x77\x31\x99\x3c\x7b\xf5\x4c\x7e\xf9\xed\x85\x98\xb1\x99\x4c\x9e\xff\x34\x92\xd1\x22\xe7\xab\x6f\x26\x93\xdb\xdb\xdb\xf1\xad\x1b\x6f\x76\x97\x93\x17\xbb\xe9\xd5\x62\x39\xdb\x4f\x40\x38\x21\x21\x98\x26\x10\x66\xcc\x78\x9e\xe7\x23\xa8\xa0\x64\xd8\xb2\xde\x9f\xdf\xc3\x6e\xb5\xd6\x24\x27\xe1\xaa\xcb\xd3\xf9\x34\x4f\x9f\x5c\x6c\xae\xde\xee\x96\x97\x8b\x2c\x5f\x5d\x7c\x2d\x56\x1b\x2f\x7f\xbe\x95\x0d\x96\x96\xeb\x69\x2f\xd3\xeb\xbc\xd8\xec\xf6\xf2\x9d\xbc\xde\xac\x73\xd7\xf7\x9b\xf1\x6c\xb3\x3a\x9b\xbc\xe7\xff\xec\x6c\xde\xbd\xde\x63\xe0\xbe\x2c\xe7\xe7\xa3\x03\xe1\x48\xc0\xb9\x7c\xa7\xa6\xf3\x1b\xf5\x06\xa8\x40\xfb\x48\x06\x42\xf5\x7a\x3a\xeb\x64\x98\xad\x96\xfd\xdb\xbb\x6c\x65\xf9\xb6\xa3\x51\xe7\xa3\x86\x5c\x65\x65\x9f\x77\x5d\x9e\x2d\x08\xe7\x6e\x35\xed\x47\x72\xbd\x5e\xe6\xbd\xba\xea\x76\xaa\x5b\x1d\xe4\x4f\xf7\xb3\x6e\x0d\xb6\xe4\xf1\x32\xef\x86\x37\x65\xf8\x3a\xe1\xb9\x97\xfb\xfd\x72\x7d\xa9\x2e\xfb\xb7\x57\x8b\xfb\x0c\x24\x51\xdd\x2c\x4f\xb5\x9e\xae\xe0\xc1\xd9\xe6\xb2\xe8\x9b\x6d\xe6\x78\xfb\xf2\x8b\x37\x5d\xd2\xfa\x5b\x68\x38\x1f\xad\x7c\x34\xe2\xbc\xde\x6a\xf1\xad\x6a\x8c\x18\x6d\xb2\xc2\x43\x1a\xcb\x41\x61\xa8\xb3\x61\x41\xea\xa2\xd4\x15\xa9\x1c\xef\x64\x65\x53\x90\x60\x6e\x94\xb1\xcd\x56\xab\xa8\x1a\x65\x1c\x04\x19\x15\x7b\xb0\xe1\x2d\x6c\x31\x2a\xa7\x95\x35\xca\x83\xab\x55\x36\x52\x67\x8c\x12\x14\x78\x0b\xbd\xc7\x13\x74\xbe\x10\x79\x15\x60\x8b\x77\xca\xb5\x5b\x15\x45\x2b\xd3\x88\xef\x0b\x83\xde\x2a\x4b\x5a\x48\x22\x29\xa4\x80\x3f\x14\x45\x54\xa5\x2c\x88\xc3\xa2\x18\xa3\xd2\xc0\x99\xa1\xc5\x58\x58\x83\x41\x43\x0b\xd4\xb7\xca\x6b\xb1\x06\x32\x5b\x45\x99\x81\x06\x34\x78\x0c\x3c\x41\x45\x2d\xa1\x51\xad\x95\x16\x92\xc5\xe3\x6f\x9c\x60\x4d\x3c\x64\x49\xe2\xc3\x26\x71\x31\x3b\x2d\x8d\xa6\xe9\x78\x57\xd6\x89\xf7\x3c\x37\x70\xf2\xb4\xdd\x00\x09\x89\x38\x0c\xd8\x6f\x0a\x44\x12\x29\xc2\x65\x83\x59\x0f\xbb\x05\x00\x25\xb1\x60\xb7\xc2\x43\x39\x71\x16\x36\x49\x8c\x30\x9b\x7f\x98\x03\x1f\x55\xbd\xd4\x82\x17\x0f\x20\xb2\x77\x54\x0c\x78\xb0\xaa\x7c\x4f\x7a\xbd\xb5\xc5\xce\x72\x38\x69\x25\x82\x1b\x36\x40\x89\x1b\x58\x8d\x5f\xd0\x8a\xc2\xe5\x54\x93\x23\xa0\xea\xc1\x4f\x60\x60\x7f\x0b\x56\xe0\xda\x27\x4d\xa8\x8b\x52\x48\x93\x42\x0e\x78\x24\xc2\x34\xa0\x67\x55\xeb\x85\xef\x74\x36\x10\x0b\x04\x1f\x8b\x7c\xd8\x56\xb9\x94\xe9\x6f\x78\x0f\x4c\x40\xc9\xc2\x5d\x1e\x67\x45\x1c\xf9\x2d\x34\xe2\x24\x2a\x66\xf2\xbe\x3b\xba\x6d\xc9\xc7\xb1\x79\x28\x9a\x71\xcd\x96\x57\xfb\xe5\xfe\x24\xa4\xcd\x10\xd2\x16\x50\x35\xae\x45\x2c\xea\x88\x58\xb4\xd4\x57\x8d\x49\x98\x2d\xca\x32\x01\x86\x69\x70\x20\xe2\x02\x11\xe1\xd2\x4d\xa1\x86\x91\x52\x5e\x33\xf7\xc2\x82\x8b\xf0\x88\x16\xf2\x86\x5c\x04\x0d\xd1\xae\xef\x2a\x08\xa7\x0a\xec\x1d\x05\xfe\x63\x05\xfe\x48\x81\xfb\xa0\x20\xfc\x37\x05\x8f\x3f\x41\x51\x70\x84\x77\x4c\x7e\x1c\x1f\xc2\x7b\xdf\x4d\x77\xb3\xc5\x09\xda\x76\x40\x3b\x34\x08\xd5\x14\xa0\x18\xc1\xa3\x22\x02\x2f\x06\x18\x84\x98\x8b\x70\x2d\xc2\x11\x43\x74\x75\x81\x03\x02\x91\x8b\x4e\xea\x8a\x14\x8e\x58\x8f\xac\x9a\xe0\x79\xde\x96\x47\xf6\x1a\xf7\x85\x61\xb8\x45\x14\xe1\xa8\xc3\x55\x35\x2d\x93\x87\x61\x36\x41\xc4\x91\xd2\x71\x48\x24\x31\xb8\x0c\x8e\xf9\x0b\xf7\x28\x35\x2a\x41\x34\xd2\x84\x03\x43\xd9\xc0\x80\x3b\xcb\x45\x66\x02\x5f\xa6\xef\x37\x0a\x99\x0d\x64\x4a\x0c\x63\x40\x88\x5b\xeb\x2d\xec\x31\x55\x05\x34\xf5\xd0\x4c\x0b\xb6\x96\x79\x47\x4a\x2a\x3b\x06\xb3\xb5\x69\x1c\x1e\x02\xf3\x7a\xdf\xed\x4e\xa0\x74\x03\x94\x91\x39\x14\x48\xe2\x72\x21\x15\xe3\x80\x04\x52\x27\xdc\xa0\x85\x6a\x52\xda\xf2\xd2\x69\xae\x88\x6b\x73\x4d\xd6\xc4\x1d\xe8\x20\x67\xa4\x9c\x90\x80\x19\x5b\xc8\x1a\xb8\xff\xc8\x0e\x0e\xf7\x00\x97\x33\x91\x22\x20\x6b\x18\x5c\x65\xee\xe1\x40\x19\xf2\x2d\x13\x29\x9f\x11\x17\xdf\x16\x47\x58\x8a\xc0\x4a\x53\x9e\xcc\x22\x76\xeb\x98\x78\x02\x42\xd0\xe4\x26\xd1\x15\x0e\xa9\xd0\x53\x0c\x54\xe0\x42\x40\x5d\x52\x64\x53\x9e\x91\x0b\x17\xb7\xd2\xb4\x09\xc7\x48\x58\x87\xcb\x3d\x3d\x82\x9c\x56\xe6\xd0\x00\x30\x99\xc2\x4c\xb1\xc9\xd7\x7f\xe0\xad\x20\x89\x54\xaa\x7f\x15\xa1\x04\xf5\x34\x1d\x34\x03\xaa\xce\xd5\x0a\xa7\x5a\x5c\x17\x64\xf5\xa4\xa2\x59\xa8\x88\xbc\x8c\x53\x68\x96\x13\x6b\x33\xbd\x1f\x4a\x10\xb7\x40\xa5\x2d\x03\xcf\xcd\x2a\x63\xb2\x47\xfe\x42\x35\x40\x81\x01\x1c\xa8\x0d\x40\x8c\x79\xd3\xb1\xf6\x60\xa0\x57\x62\x02\xd6\x90\xee\x00\x81\x6f\x81\x93\x2f\x8e\x0c\xd5\x91\xfe\xd8\x91\xe9\xd8\x91\xfe\xc4\x91\x4d\xf1\x05\x1c\x89\xb4\xed\x8f\x1d\x19\x3e\x72\x64\x60\x21\xa5\x23\x43\x71\x64\xa9\x11\x8c\x82\xea\xc8\x50\x52\x02\x2c\xa7\xf7\x09\x2f\x1c\x19\x8b\x23\xfd\xc1\x91\x4d\x71\xa4\xf9\xd8\x91\x3e\x42\x16\xea\x31\xae\x5e\x3b\x34\x01\xf9\xd0\x13\x0c\x0d\xc1\x87\x46\x60\x68\x0d\x86\x29\x37\x2a\x15\x04\xb9\x96\x40\xb1\x2d\x48\xed\x10\x04\x43\x40\xd8\x1a\x10\x56\x15\xf7\x1f\xa2\xe0\xbe\x80\x28\x72\x80\x36\xee\x25\xe4\x34\x00\x1d\x7b\xb8\x1e\x48\x25\xd6\x56\x6f\x7a\x38\x0e\x29\xae\x01\x0c\x86\x70\x85\x02\x1a\x3c\xc2\xaa\x85\xac\x87\x2a\x8d\x1f\x2b\x55\x2c\xf5\xca\x95\x42\x8e\x74\x64\xe1\x5f\x02\xcd\x70\x07\xb2\x2d\x97\x51\xc3\x5a\x26\x25\xc5\xf6\x08\xf5\xf5\xd3\x30\x38\x69\x26\xa3\x19\x37\x0f\x45\x73\xbf\xb9\xdc\x5c\xe7\x93\x70\xf6\x87\x86\x0d\x4d\x85\xee\x99\x6d\xb5\xb4\x8c\x45\x06\x12\x0d\x6c\x4a\xe2\x8c\xc8\x9a\x11\x51\xa9\x7b\x2c\x60\x13\x51\x4e\x92\xc8\xe8\x62\x39\x96\x48\xe6\x48\x0e\xda\xc9\x05\x93\xb1\x6b\xdb\xbe\xd2\x37\xac\x15\x90\x60\xdb\x4c\x71\xa6\x67\x5a\xd5\xaa\xaa\x12\x4e\x1b\x5a\x50\x64\xb2\xe7\xc1\xbc\xf8\x18\xc1\x69\x03\xd3\x33\x7c\xd0\x32\x3c\x0d\x9a\xb0\xc6\xeb\x03\x9b\xbc\x9f\x5b\x7d\x92\x32\x1f\xee\x5d\x57\xdd\xfa\xfa\x04\x8b\x70\xa8\x3d\x14\x8b\xa3\xd4\xfa\x86\xe0\xf7\x19\xad\x06\xc2\x9a\x75\xda\xd7\x49\x8f\x04\x55\x70\xb0\xb4\xd9\xf9\xf7\x05\x99\xb1\xc1\xa7\x43\x31\xf0\x7d\x21\xa2\xc3\x39\x21\xa0\x8f\xa1\x7f\x8c\x62\xc8\xc4\x08\xe4\xff\x47\x33\x8f\x93\xe3\xc3\xf0\x5d\xf5\xd7\xa7\x99\x31\xde\xa9\x37\x47\x8d\xd2\x47\x6d\x86\x75\xf6\x06\x0f\xf7\x61\x2f\xd6\xbd\x70\xdc\x82\x84\x6a\x6b\xbc\x01\x75\xe1\x7b\x74\x83\x45\x1d\xa4\xd7\x6c\x7c\xff\xa9\x31\xa2\x35\x96\x2c\x9f\xd6\xd1\xcc\xa6\xeb\x59\xd7\x9f\xc0\x92\x0e\xb0\x94\x44\x60\xef\xb4\x8e\x3d\xbf\x2f\x22\xbf\x60\x42\x5d\xa0\x0b\xeb\xe1\xf8\x3d\xc1\xe6\xdd\x73\xc4\xdf\xdf\x4f\xc4\x5e\xa7\xf0\x33\x15\xd5\xf3\x97\x67\x5f\xb9\x9b\x41\x4a\x73\x1f\x49\xe5\x2d\xeb\x52\xc1\x2e\x07\xef\xef\xb0\x15\xd6\x53\x8a\x6a\x35\xfb\xfa\x52\xa9\xe9\xda\xe1\x3c\x77\x78\x55\xe1\xfd\x40\xf3\x37\x50\x4e\xf8\x29\xcb\x71\xf8\x6a\xe6\xf7\xf8\x93\xbf\x00\x98\xa3\xd5\xb1\x40\x10\x00\x00" + +func font_fontello_svg_gz_bytes() ([]byte, error) { + return bindata_read( + _font_fontello_svg_gz, + "font/fontello.svg.gz", + ) +} + +func font_fontello_svg_gz() (*asset, error) { + bytes, err := font_fontello_svg_gz_bytes() + if err != nil { + return nil, err + } + + info := bindata_file_info{name: "font/fontello.svg.gz", size: 1707, mode: os.FileMode(436), modTime: time.Unix(1432518658, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _font_fontello_ttf_gz = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\xe5\x57\x5d\x6c\x5b\x47\x76\x9e\xb9\x97\xbc\xa4\xa8\x1f\x52\x16\x45\xc9\xa2\x4c\x0f\x75\x2d\x4a\x16\x2f\x29\x99\xfa\xb5\x2c\x33\x0a\x29\x4a\x8e\x65\x3b\xb4\xac\xb8\xa4\x93\x4d\x48\x51\xd4\x8f\xa3\x1f\x56\x92\x0d\xe5\x07\x41\xd0\xcd\x16\xa9\x90\xa6\x46\xb0\x30\x8a\x36\x05\xb6\x0b\x67\x51\xf4\x69\xe8\x64\x9b\x6c\x11\x20\x8b\xa2\x5d\x6c\x8b\x5d\xa0\x45\x83\x45\x1f\xfa\xb3\x0f\xfb\xe0\x45\xb7\xd8\x87\xb6\x0b\xf4\x21\x52\xbf\x73\xef\x95\x2c\xdb\x72\x0b\x2c\xfa\x56\x52\x9c\xf3\x9d\x33\xdf\x9d\x39\x73\xce\x99\x99\x2b\xc6\x19\x63\x0d\xec\x6d\xa6\xb2\xc2\xf3\xd7\x7a\x13\xc9\xee\x0b\xff\x0e\xcb\x2f\xf0\xbb\x5e\x5a\x2d\x56\xfe\xf6\xf8\xf1\x4f\x19\xe3\x13\xf8\x5d\x2c\xdd\xde\x12\xcc\xfc\xd4\xbd\x84\xc6\xb3\x50\x59\x5c\x7d\xf7\xce\x9d\x3c\xf4\x25\xc6\x6a\x2b\x8b\xc5\xcd\x0a\xec\x3e\xe8\xb3\x90\xee\xc5\x95\xd7\x16\x7e\xe5\xff\x70\x98\x31\xe5\x0e\x63\xce\x1f\x2e\x95\x8b\xf3\xda\xc8\x4c\x23\xba\x72\xe8\x1f\x5a\x82\xc1\xf5\x2f\xea\xb7\xa1\xa3\x9f\x9d\x5a\x5a\xdd\xda\x0e\x7f\x93\xc6\x77\x7f\x82\xa6\x7b\x65\xbd\x54\xac\x69\x75\x19\xd0\xff\x11\x7a\x60\xb5\xb8\x5d\x61\xdf\xa9\xfd\x57\xe8\xff\x01\x5d\xac\x15\x57\xcb\x3f\xfa\xa3\xe0\x09\xc6\x6a\xfc\x98\xe3\xc7\x95\xf5\xcd\xad\x3f\xfd\xe9\xf4\x59\xf8\xf2\x33\xf4\xaf\x57\x36\xca\x95\x7f\x7a\x55\xfd\x06\x63\x2d\xff\x00\xfd\x0d\xc6\xd5\x97\xf8\x1d\xe6\x64\x6e\xe5\x75\xe5\x73\x58\xde\xb3\x24\xff\x29\x3b\xc3\x15\x8c\xc0\x9c\x2a\x3b\xf2\x93\x5d\xc8\xcc\xb3\xf1\x07\xec\x81\x5b\x9d\xd9\xbb\xc9\x6e\xa8\x33\xec\x2e\xcc\xfc\x80\xa0\xda\xbf\x76\xdb\x36\x01\x8d\x9b\xba\x83\x75\x43\x6a\x90\x1c\x13\x60\x84\xbd\x3d\x22\x3c\x60\x24\x5b\xf9\xc3\x31\xb8\x76\xf4\xdc\xff\xcf\x3e\x88\xd1\x5e\x55\xbd\xa1\x7a\x98\x9b\x2d\x31\xf7\x77\xaf\x0a\x4d\x51\x62\x51\x3e\x10\xe9\x68\xe0\x81\xc4\x50\x67\xb3\x5f\xf3\x72\xcd\x15\x68\x09\xf8\x5d\x0d\xbc\xab\xa3\x17\x0a\xbe\x51\xde\x11\x19\xec\x8a\x74\xb9\xb4\x0e\xb4\x91\x81\xe1\x24\x1f\x8e\xf4\xf2\x38\xef\x1a\x1c\x18\x7a\x86\x0f\x0d\xdb\xc6\xfe\xc4\x49\x28\xf8\x9e\xe3\x89\xc0\x49\x1e\x68\x19\x1e\x4a\xb4\xd0\x60\x5e\x0e\x35\xc4\x95\x73\x33\xdb\x33\xca\xf5\xad\xeb\xbc\xdd\xed\x5a\xf2\xd4\x36\x75\x6b\x4e\x6f\xb6\xde\xe5\xba\x7c\xbc\xad\xc6\xe5\xf0\xbd\xe9\xae\xf3\x05\x5b\x9e\xd7\x7c\xda\x64\xc0\xe1\x74\x77\x7b\xbc\xee\x05\x97\x9b\x7b\x9c\x4b\xee\x86\x96\x4e\x8b\xeb\xbe\xdc\xda\x56\xe3\x56\x1b\xdf\x74\xd5\x71\x6f\x7b\x20\xeb\xf4\xba\x2e\xf8\x1d\x8e\x73\x0d\x35\x0b\x2e\x0f\x7f\xf9\xdc\xec\xec\xed\xd9\xd9\x6d\xea\xf5\x85\x9a\x83\x09\xad\x41\x6b\xce\x72\xe7\x58\xbd\xfb\x52\xbb\xcf\xe3\x5a\xac\xa9\x1b\x73\x6a\xe3\x21\x67\x83\x56\x97\xf0\xb6\x07\xbd\xbc\xce\x65\x72\x8f\xb7\x89\x98\xab\xce\xe5\xcf\x5a\x54\xaf\xdb\x6d\x52\x9d\xe9\x76\x50\x2f\x9b\x44\xab\x0a\x99\x7a\x8c\xff\x1b\xf3\xb2\x93\xac\x97\x79\x3e\x35\xf4\xf6\xa6\x3a\x55\x8d\x45\x9b\x10\xba\x2e\xbd\x23\x42\x11\x19\xee\x4f\x04\x9c\xb6\x3e\xfc\x98\x7e\x9e\x5b\xfa\x4f\x42\x2d\xaf\xb6\x84\xb8\x08\xbc\x1a\x10\xfc\x84\x25\x2c\xd3\x49\x53\xb1\x2c\x9f\x3e\x34\x1f\xa6\x3c\x82\x29\xaf\x7b\x7b\x7b\x37\xd5\x3f\x56\xeb\x91\xd7\x30\xf2\x7a\xbc\x56\x53\xcd\xbc\xc6\xb9\x16\xe2\x49\xce\xfd\x1a\xa5\x52\xef\x88\x2b\x49\x47\x48\x69\xf1\xbb\x5a\x02\xca\xd7\xbf\xf9\xa3\xbb\x8e\xf7\xbf\x7c\x8f\x77\x18\xa3\xfe\x2f\xe6\xdf\xc8\x7e\xb0\x34\xae\x8c\xad\xbc\x7f\xef\xbd\xca\x88\x9a\xf9\xa2\x99\xff\xd6\xe2\x07\xca\xdd\xbf\xf9\x7d\xed\xbd\xdd\x3f\x38\xd1\xd3\xfc\x45\x26\x79\xf3\xce\xb7\xdf\x5f\x1b\x75\xa4\x16\xee\x5e\x7e\x63\xfe\x8b\xe6\xfd\x7a\x6a\x52\xeb\x10\x8d\x6e\xcc\x8b\x32\xa2\x7a\xea\xf4\x6b\x7a\x18\x15\x33\x90\x74\xb6\x24\x42\x4a\x22\xa9\xf4\x27\x42\x4e\x15\x4e\x44\x92\xa8\x02\xf5\xd8\x4c\x7a\xb7\x35\x3d\xe3\xa8\x3b\x16\x8a\x8c\x86\x9d\x11\xe3\xd2\xc5\x8b\x7d\x1d\xae\x8e\x91\xee\x76\xbf\x47\xfb\xe4\x2d\xf9\xb6\x63\xfb\xb3\xdb\xa9\xf4\x95\x2b\xe9\xd0\x48\x6a\x68\xa4\xa3\x4d\x69\x0d\xb5\xe2\x2f\x10\x19\x18\x4d\x8e\xf1\x9f\xe4\xde\x02\x47\x79\x93\x69\xb4\x6e\x47\x2f\x4e\x8c\x46\x96\x60\xe7\x70\x32\x5c\x67\xaf\xb0\xc6\xf1\x86\xaf\xe5\x67\xa7\xd2\xc9\xb3\x83\xc2\xef\x52\x34\x04\x42\x73\x51\x2a\x06\xe0\x06\x1f\x4e\x0c\x6b\xcd\x7e\x6e\xb9\xd8\x05\x17\x61\x54\x92\x9c\xaa\x38\x11\x72\xb4\x50\xa8\x22\x03\x43\x89\x00\x40\x9c\x27\x95\x80\x93\xf2\x16\xe9\x1a\x1a\x1c\xe8\x0a\xf4\x27\x92\xbc\x25\xd1\x75\x40\x99\xbe\x31\x3a\x1d\x1b\xe7\x19\x47\x4f\x2a\x1c\xe9\x54\x95\xaf\xd3\xc2\x26\xb2\xdc\x51\xe7\x13\x58\x99\x76\x2a\x7e\x21\x3b\x79\xfc\xb4\xcf\xa5\x8f\x44\x84\xaf\x81\x7f\xf5\x03\x2a\xce\xdb\xb3\xfc\x77\x4c\xff\x3f\x79\x9d\xa7\x93\xf1\xe9\xb3\x37\x62\x6a\x67\x67\x78\xa2\xdb\x91\x99\xb2\xfb\x5f\x56\x27\x0c\xe3\xaf\x02\x6d\xbc\xbe\xd9\x77\x65\xf7\xc5\xd4\x95\x2b\x29\x44\x62\x64\x20\x12\x68\x6d\x6f\x53\x02\xbe\x36\x8f\x82\x58\x8c\xa4\xda\x95\xdf\xb3\x0a\x7e\xf7\x97\xf9\xb7\x94\xd7\xff\x6c\x5b\x7b\xe7\xef\xa3\x71\x3e\xa1\x3e\x7b\xc5\xd7\x5c\xdf\xda\xca\xed\x6e\x7b\xef\x7f\xa8\xbe\xa3\x0a\xd6\xc2\x42\xc8\x55\xe8\x78\xbd\x13\xb9\x0a\x0f\xf6\x37\xdb\xe9\x6a\x1c\x18\xea\x0f\x27\x02\x27\xb8\x3e\x18\x6e\xe4\xae\xc1\x30\xbe\xfc\x57\x73\xa3\x3d\xbb\x95\xee\xb1\xb1\x6e\x7e\xa7\x67\x74\x6e\x77\x4d\x15\x3f\xd8\x4d\xf2\xbf\x98\x9f\x27\x9b\xf2\x79\xcf\xe8\x68\xcf\xdd\xbb\x5f\x4d\xf0\xc9\xbf\xdc\xbe\xbb\xcd\xec\x3d\xa2\x7c\xae\xe4\x58\x2d\x66\xd2\xb1\x47\xda\x5b\x7d\x75\x0e\x86\x3d\x82\x43\xc1\x9a\x0a\x13\x0d\x9a\x6d\xd8\xb4\x34\x1e\xb2\x2b\x3b\x81\xf6\x90\xff\xab\x3f\xf1\x87\xda\x03\xf4\x53\x72\xa4\x3f\xb4\xf1\x3b\xa1\xee\x10\xfe\xe6\x2d\xb1\xfb\xa5\x25\xcd\xfb\x62\xef\xbf\xd4\x63\x6a\x2d\xe6\xd4\x3e\x6e\xab\xe1\x98\xcf\xdc\x73\x68\xcc\xec\x0f\x1e\xec\x4e\x34\x74\x40\xb5\x34\x63\x1f\xaa\xc7\x44\xe0\x81\xb5\x9f\x1e\x98\x3b\xeb\x81\xb5\xad\x1e\xec\xef\xbe\x9f\x07\x60\x6d\xfe\xf9\x81\x95\xe8\xb4\x44\x9a\xef\x97\xca\x97\xca\x6f\xb3\x53\x98\x2f\xe0\xe0\x54\xf7\x38\x3c\xb1\xd1\x5c\xd4\x44\x06\x9e\xe1\x5d\xd4\x0c\xe1\x50\x1c\xa6\x86\x8e\x41\xec\xbb\x2f\xbd\x97\x7c\x86\xef\xde\x3d\x34\x97\x7c\x24\x7d\x0f\x75\xaf\xf7\xde\x3d\x6f\x25\x40\xe0\xa3\x8f\xbc\x4f\x12\xbd\x71\x22\x98\xf7\x1a\x7e\x3f\x5e\xfa\xc3\xfe\x57\xbc\x63\xff\xc9\x6a\xd5\x07\xe4\xd2\xdf\xdd\xfa\x30\x6b\xc9\x0d\x71\xb0\x33\x70\xa1\x53\xee\x99\xed\xb3\x75\xc7\x3a\x7a\xe1\xfd\xae\xa3\xef\xd0\x2d\x6b\x7d\x3c\x34\x92\x8a\xb7\x0e\x15\x6f\x12\xea\xb7\x2c\x49\x6c\xf5\x1d\xca\xaa\x6d\x6f\xb4\xd9\xdf\x62\xbf\xe0\xdd\x7c\x89\xef\x2a\x09\x65\x4d\xf9\x8e\xf2\x33\x6b\x0e\xe6\x61\xcb\x4c\xdb\xbf\x71\xf0\xce\xb2\x89\xb6\xa3\xb6\x62\x3f\x75\x8c\xfd\xf3\xc1\xbc\x83\x6c\xff\xa6\xe7\xf0\x73\xd0\xc6\x0a\x73\xb1\xf3\x36\x56\x61\x9f\xb0\xb1\x03\xf8\x92\x8d\x9d\xa8\xaf\x59\x1b\x6b\xb0\xbf\x62\x63\x0f\x8b\xb2\x45\x1b\xd7\xb2\x26\xf6\x01\xbd\x2d\x38\x6a\xa0\xdd\x64\x1f\xd9\x98\x33\x1f\xf7\xda\x58\x61\x0d\xfc\xa4\x8d\x55\xd8\x63\x36\x76\x00\x9f\xb7\xb1\x93\x05\xf8\x65\x1b\x6b\xb0\x97\x6c\xec\x61\xd7\xf9\xa6\x8d\x6b\x59\x84\xff\x75\x7a\xbd\xf2\xda\xc6\xf2\xe2\xd2\x96\xe8\x4e\x9f\x16\x89\xbe\x33\x83\x62\xee\x35\xb1\x0e\xd3\xf2\x5a\x71\x45\x14\x6f\x6d\x2d\xad\x6f\x6c\x8a\x71\xb1\xb0\xbe\xb6\x55\x5e\x59\x59\x8f\x97\xd6\x57\xf7\xf1\x4c\x79\xf1\xd6\x4a\x71\x63\x5f\xdd\x97\xd7\xcb\x1b\x9b\xcb\xeb\x6b\xe2\x4c\xbc\x6f\xdf\x34\x55\x5e\x2b\x6f\x14\xb7\xca\xf3\x34\xfa\xe6\xed\xc5\xc4\xd6\xd6\x82\x58\xd8\x58\x5f\x15\x93\x36\x43\x54\x36\xd6\x6f\x96\x4b\x5b\xf1\xa5\xad\xad\xca\x68\x6f\xef\xe1\xf9\x58\x9a\xad\xb3\x0a\x7b\x8d\x6d\x20\x4d\x8b\x78\x11\xd8\x62\x02\xc7\x77\x9a\x9d\x86\x4c\xb0\x3e\x76\x06\x89\x10\x6c\x0e\x0c\x01\xa6\xc5\x5a\x66\x6b\xac\xc8\x56\x60\x29\xb2\x5b\x78\x62\xc9\xec\xd9\x84\x3e\x8e\xdf\x02\xb4\x35\x58\xcb\x60\xac\x00\xc7\x59\x09\xed\xea\x13\xf6\x19\xa0\x45\x3c\xbf\x82\x51\x36\x9e\xe8\x7d\x5c\xbf\x0e\x44\x73\x2c\x9b\x76\x01\xbf\xe2\xf0\xee\x71\xd6\x14\xd0\x9a\xc9\x2c\x9a\xd6\xf9\x03\xdf\x37\xd9\x6d\xcc\x96\x80\x75\x0b\x4f\x91\x97\x1b\xa6\x57\x82\x4d\x3e\x36\x86\x40\x3c\xa8\xef\x26\x2c\x25\xd8\xe3\x66\x54\xb6\x60\x1d\xc5\x35\xdf\xfb\xd4\xf5\xd9\x15\x6e\xd5\xdd\xd1\x1f\xd8\xb9\xc2\x55\xee\xe0\x4e\xae\x71\x17\x77\xf3\x1a\xee\x51\x4b\xeb\x8b\x6e\xe4\x63\xb9\xb2\xb9\xbc\xa9\x6d\x96\x8b\x1b\xa5\x25\xc7\xad\xcd\xf2\x86\x93\x9a\x4d\x6d\x65\x7d\x71\xfd\xd6\x96\x63\xb5\xbc\x76\xcb\x51\x59\xb9\xb5\xa9\x95\x8a\x6b\xa5\xf2\x8a\xb5\x4f\x38\xde\x6e\xbd\x87\xa7\x90\xcc\x10\x92\xbd\x90\xcb\xe4\x85\x98\xfe\x8c\x35\x5c\x9d\x96\xda\xb5\x1b\x39\x39\x10\x94\xdd\xf9\xc2\x82\xd8\x79\x21\x27\x95\xce\xe2\xf7\xdc\xd8\x26\xa5\x92\x3e\x17\x0c\x87\x25\xcb\x4b\x96\xd6\x27\xee\x63\xbc\x74\x21\x15\x93\xdc\x90\xa2\xb0\x10\x93\x8a\x21\xe6\x85\xfc\x7e\x56\x3a\x22\x37\xee\x77\x73\x4f\x3a\x53\xca\xcc\xbc\x98\x0b\xeb\xe1\xe0\x4e\x4e\xc8\x6c\x36\x17\x96\xe3\xf9\xa0\x90\x23\x84\x46\xf2\x79\x51\xb5\x48\xc5\x79\xd9\x0d\x93\xad\x09\xd9\x47\xfd\x7d\xc4\xfc\x7e\x36\x27\xe0\xc4\x4e\x51\x48\x4f\x36\x57\x80\x45\x50\x9f\x87\xd0\x10\xa1\xa1\x42\xb0\x90\xcf\xe7\x83\x92\x47\xf3\x79\x5d\xb2\x6c\xae\x9c\xcf\xc7\xa4\x6a\x08\x8c\xe3\xe8\x2c\xc2\x21\x67\x3a\x9b\x93\x4e\x3d\x25\x35\x3d\x05\xf7\xf3\x92\x17\x62\xd2\x61\xe8\xf0\x4b\xcc\x57\x9d\x73\x29\x41\x3d\xd6\xe4\xd4\x4a\x56\xc8\x94\xa4\xda\x13\x86\x3d\x2d\x76\xc4\x0e\xc6\xae\xf6\x39\x3b\xb1\xac\xab\xb9\x42\x36\x58\x9c\xc9\xe7\xf4\x3c\x7a\xc7\xaf\xe5\xd0\x15\xa4\x45\xd9\x33\xc7\xa4\xd3\x90\xae\x74\xf4\x3e\x52\x6b\x86\x46\x83\xaa\xa7\x74\x84\x58\x4f\x15\xa5\x32\xb7\x20\x79\x09\xf3\x4b\x67\x4f\x4c\xba\x0c\x41\x4e\xd6\xa6\x4b\x9f\x39\xd8\x9c\xa0\x11\xe4\x78\x21\x4f\x94\xc2\x84\xe9\xa4\xdb\xb8\xef\xaa\x65\xe9\x4c\xaa\x27\x7c\x10\xec\x1a\xe3\xd1\xe0\x7b\xac\x51\x78\x14\x2e\xa4\xb1\xe2\x82\xc8\xec\xe8\x45\x4a\x84\x19\x29\x16\xa4\x68\x4a\x11\x84\x93\xfb\x5e\x4a\xb5\x53\x2f\x4e\x58\x53\xd4\x3e\xe5\x71\x79\x0a\x4f\xb1\xe0\xc3\xa5\x1d\x7e\xa8\xce\x30\x17\x74\xbf\xd6\xa3\x66\x72\xe1\xa0\x1e\xce\xf7\x84\x63\xb2\xde\xa8\x2a\x4a\x46\xce\x17\x27\x62\xb2\xc1\x00\x51\x08\x59\x97\xbe\x48\x8f\x03\xe8\xa9\xbc\xac\x27\x6d\x06\x5a\x3d\xb4\x98\xf4\x62\x18\x9f\x19\x12\x81\x08\x94\x30\xaf\x6c\x48\x17\xc4\x4e\x41\xc8\x06\x04\x2d\x26\x7d\xc6\xf4\x6c\xae\xea\x98\x9f\xc8\x9f\x92\xf5\x65\x7d\x3b\x26\x1b\x8d\xe9\xab\xb9\xe9\x6b\x96\x31\x18\x86\xbd\xc9\xb4\x1f\x33\xaa\xcc\x9b\x7e\x21\x57\xf5\x7a\xd3\x92\x17\x53\xd2\x1b\xa5\x22\x45\xe9\xa6\xaa\x75\xd4\xd4\xa3\x91\x3c\x80\x4c\xa8\x9d\xd9\x5c\x95\x82\x87\xd5\xa6\x76\x90\x5e\x9a\xb6\x27\xac\xe3\xb1\x7d\x1c\xb4\xfa\xe9\x11\xd4\x3e\x59\xf2\x58\xc9\x14\xfc\x9f\x82\xf5\xd1\x54\x3d\x25\x81\x55\xc6\x9a\x74\x44\x0b\xd5\x94\xbc\xcf\x39\x37\x73\xd5\x64\xb0\x2a\x53\x32\xb3\x39\xe9\xd5\x53\x22\x23\x6b\x51\x94\x1e\xc4\xb7\x90\x12\x05\x4c\xff\x5d\x9f\x8f\xe3\x7f\xfe\x54\x6a\xa7\x50\x3d\xa6\x45\xe5\x46\x34\xd8\x81\x30\xf9\xb1\xb6\xa6\x68\x4c\x36\x1b\x55\x4e\x32\x80\x38\x93\x6c\x31\xf0\xfe\x0c\xd9\x6a\x54\x1d\x24\x8f\x1b\x55\x27\xc9\x36\xa3\xaa\x91\x0c\x1a\x55\x17\xc9\x76\xa3\xea\x26\x79\xc2\xa8\xd6\x90\x0c\x19\x4c\xd6\x47\x7f\x0d\x47\x4e\xc2\x91\x10\x06\x10\x70\x84\x64\x18\x8e\x90\xec\x80\x23\x24\x75\x38\x42\xf2\x14\x1c\x21\xd9\x09\x47\x48\x46\xe0\x08\xc9\x2e\x38\x42\xb2\x1b\x8e\x90\x3c\x6d\x88\x31\xb3\x9e\x7a\x0c\x4c\xeb\x2b\x88\x34\x92\x50\x48\x9b\x31\xc7\x1e\x39\x4d\x45\x15\x35\x64\x4f\x54\xf6\x60\xbb\x18\xa8\xd4\x29\xf1\x94\x70\xeb\xc5\x11\x9d\xce\xaa\xff\x91\x81\x7a\x89\xc9\xd8\x41\x0e\x78\x40\x1a\x3d\x92\x37\xf7\x99\x8b\x8b\x1f\x8e\xca\xa3\x5d\xbd\x86\x18\x34\xfd\xec\x03\x87\x67\x9e\x1c\x1c\xdb\xe7\xc8\x49\xc9\xce\x02\x9f\x98\x07\xed\x44\x52\x1f\xa9\xf6\xf2\x66\xac\xe4\x0c\xd6\x0d\x47\x8f\xf6\x13\x55\x5b\x1c\x89\xc9\x84\x11\x6f\x19\x8b\xc9\xfe\xff\x8d\x8a\x0a\x2b\x81\x3e\x80\x54\xb0\x40\xa7\x88\x8b\x29\xda\x99\x08\xe1\x73\x3b\x3b\x53\xfa\x14\xb6\x72\x0e\x67\x36\xce\x3c\x6c\xd7\x7e\x8e\xb7\x5a\xcc\x3f\x88\x23\x24\x80\xea\xc7\x9f\x49\x91\x35\xe9\x68\x79\x27\xae\x0b\x31\xb6\x83\xb1\x86\x1e\x76\x8b\xb8\x35\x86\x74\x60\x4c\xb0\x84\x2c\xd0\x66\x1e\xbf\x9a\xfb\x58\x11\xaa\x08\x7e\xac\x44\xd4\xb6\x7c\x8a\x0e\x38\x37\x8e\x4a\xdd\x64\xeb\x93\xd8\x5a\xe9\xc7\xf7\x49\x81\x0e\x19\xeb\x24\x57\xd2\x85\x79\x5d\xaa\xe9\xe2\x3c\xba\x95\x74\x31\x08\x5c\xa0\x03\xe6\xf1\x67\x8a\x70\x09\xa7\xae\x3e\x89\xdc\xe9\x98\x61\x12\xeb\x82\x30\x67\xc1\x78\x47\x4c\xa2\x5b\x47\x99\x03\xbb\x17\xb1\x77\xa2\x90\x9c\x4f\x8c\x8a\x11\x69\x45\x9d\xa6\x13\x68\xb3\xd6\x11\xf6\x70\x2e\xa4\x7c\x98\x62\x20\x60\x71\x46\xec\x18\xe8\x63\x08\xcd\x88\x69\x96\x6e\x6c\x1a\x21\x26\xf5\x29\x9a\x8c\xb2\x75\xd6\x0c\x19\x2d\xc0\x8e\x28\x9b\xcd\xc5\xc5\x18\x2e\x3e\xf2\xd8\x36\x0a\xf2\x65\x3f\xe4\x5a\x27\xb4\xe7\x0e\x5f\xad\x56\xa2\x8e\xaa\x5c\x3b\x33\x3a\x95\xef\xa8\xed\x41\x7a\x3f\x35\x05\xba\x7b\x1f\x5f\xe2\x7e\x2a\xcf\x19\xba\x88\x53\xd4\x26\x71\xea\x8e\xe5\xe3\xd5\x28\xf7\x63\xe3\x8d\x1d\x98\xb3\x87\xcd\xe7\x1f\x65\x1f\xc9\x49\x1a\x72\x30\x7a\xe4\xa0\xcf\x18\x72\x28\xba\x83\x89\xa9\x58\xe0\xed\x93\x1c\xa4\x25\x2e\xa3\xa0\x8e\x1f\x54\xd8\x7e\x74\xa9\xb8\x74\x94\x7a\x1c\x9b\xc4\x1a\xee\x59\x1c\x16\x38\xa0\x7f\x8d\x52\x9c\xfa\xbf\xaa\x3e\x72\x9f\xce\x95\x31\x1d\x47\xc7\xa1\x7c\x87\xf3\xb6\x8f\x29\x0a\xc6\xfe\xfa\xd3\xb4\xfe\xb0\x6e\x07\xc0\x5e\xc7\xc1\x92\x27\xb0\xe4\x66\x6b\x73\xe2\xea\xc6\x3e\x6c\x8a\xcb\x33\xd8\x8b\x99\xa7\xd8\x27\x71\xd6\x72\x7f\x93\x4c\x00\x4f\x19\x72\x00\xe2\x02\x45\x2d\x83\xb8\x8a\x49\xdc\x53\xfb\x71\x7a\xce\xa0\x72\x94\x17\x00\x2f\x1a\xf7\x19\x7b\x16\x60\x1a\x80\x13\xb8\x64\xdc\xe7\xa6\xe5\x32\x80\x69\xb9\x42\x9c\x14\xc0\xf3\xc4\x21\x90\x25\x0e\x81\xab\xc4\x21\x30\x43\x9c\x24\xc0\x35\xe2\x10\x98\x25\x0e\x81\x17\x88\x43\xe0\x3a\x71\xc6\x01\x7e\x83\x38\x04\x72\xc4\x21\x90\x27\x0e\x81\x1b\xc4\x49\x03\xbc\x48\x1c\x02\x2f\x11\x87\xc0\xd7\x88\x43\xe0\x65\xe2\x3c\x03\xf0\x0a\x71\x08\x14\x88\x43\xa0\x48\x1c\x02\x73\x86\x1c\x3e\x08\x73\x89\x14\x79\x0e\x68\xde\x44\x63\x40\x65\xb3\x9e\xa0\x9c\x87\xb2\x60\xc8\x91\x03\xf6\x22\x29\x26\x7b\xc9\x44\xc4\x5e\x36\x11\x51\x6f\x1a\xf2\xec\x01\xf5\x55\x52\x4c\xea\x8a\x89\x88\xba\x6a\x22\xa2\xae\x19\x72\xf4\x80\xba\x4e\x8a\x49\xad\x98\x88\xa8\xbf\x69\x22\xa2\x6e\x18\x1f\xd7\x38\x94\xfd\x37\xa3\x54\x54\xba\xcb\x52\x3d\x95\xdd\xa6\xfb\x24\xc6\xf0\x92\xfd\xc3\x19\xbc\x80\xf0\xf7\x71\x28\x5b\x7b\xbf\x52\x65\xce\x14\x5e\x18\x7a\x2c\xe9\x7e\x44\x7e\x0f\x77\x47\xcd\x61\xa4\xb2\x89\xea\x29\xfe\xee\x55\xd4\xe9\xbb\xb9\xaa\x3a\x3f\x51\x8d\x90\xf6\xe7\xee\xb7\xf1\xbf\xe4\xf8\xbb\x25\xbc\x31\x81\x82\x77\xe2\x7c\x95\xd5\xf5\x7c\xc6\xf7\xbe\x21\x1d\xbf\x8b\xdb\x61\x82\xfd\x37\x88\xf0\x61\x56\x54\x18\x00\x00" + +func font_fontello_ttf_gz_bytes() ([]byte, error) { + return bindata_read( + _font_fontello_ttf_gz, + "font/fontello.ttf.gz", + ) +} + +func font_fontello_ttf_gz() (*asset, error) { + bytes, err := font_fontello_ttf_gz_bytes() + if err != nil { + return nil, err + } + + info := bindata_file_info{name: "font/fontello.ttf.gz", size: 3490, mode: os.FileMode(436), modTime: time.Unix(1432518658, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _font_fontello_woff_gz = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\x65\x56\x67\x34\x9c\x5b\xd4\x9e\x31\x8c\x36\xcc\xa8\x21\x46\x8c\x76\x75\x46\x2f\x41\x88\x16\x65\x10\xbd\x07\x63\xb4\x21\x3a\x89\x9a\x51\x27\x88\x16\xbd\x64\x08\x41\x24\x88\x68\x41\xb4\xab\xb7\x88\x88\x96\x10\x9d\x11\x25\x48\x82\x88\xf2\x4d\xee\xbd\xdf\x8f\x6f\x7d\x67\xad\xe7\x3d\x67\x3f\xfb\xd9\x7b\xaf\xf5\xbe\xef\x5a\xe7\x09\x31\xd2\xd6\x06\x00\x01\xa4\x45\x9f\x0b\xa0\xff\xb3\xb3\x99\xfd\x1b\xff\xff\x65\x64\x2a\x21\x05\x00\x00\x35\x49\xc7\x3f\xb0\x50\x15\xbc\xf5\x1d\xed\xed\xe4\x4b\xe2\xf0\xa4\x58\x89\xb4\xeb\xbd\x67\x67\x6f\x46\x07\x07\x22\x48\xe7\x5e\x12\x47\xf3\x1f\x00\xae\xbe\x6e\xde\x24\xee\x3d\x00\x40\x91\x09\x00\xd0\xfa\xe2\xd3\xd2\xac\xdd\x9c\x02\x48\xb5\x94\x2e\xa4\x34\xd5\x7f\x80\xb9\x79\xdd\x77\x25\x71\x5e\x00\x00\xf9\x2d\x92\x76\xf0\x88\xb9\x50\xde\x1d\xe3\x44\xd2\xd0\x36\x90\xf2\x32\x24\xc8\x81\x15\x4c\x18\xdc\x49\x24\x89\x23\x92\x62\xd2\x2c\x00\x1f\xe5\x22\xe8\xa9\xbb\x77\xe0\x3d\x00\x00\xf2\xa7\x0f\x37\x09\x82\xdc\xa4\x49\x5e\x3e\x68\x92\x0e\x22\x4a\x8a\x59\xff\x80\x9a\x8d\x52\xd4\xdb\xe9\x1e\x69\x2e\x44\xf3\xbf\x5a\x04\xa0\x9c\x76\xfb\xae\x93\x37\x86\xc4\x91\xe6\x00\x43\x00\x00\xb2\xb1\xd1\x22\x0e\x4e\x5f\x9f\x80\x40\x00\x80\x6e\x9e\xa4\x31\x25\xc1\xa7\x6a\x49\x5f\xd1\xd7\x1f\x43\xaa\xa5\x47\x92\x62\x92\x1e\x10\xb6\x80\x05\xc5\xdd\x2b\x44\x3b\xba\xa4\x38\x15\x76\x75\x0d\x77\x75\x9b\xf5\x35\x24\xe0\x70\x25\x94\x37\xa5\x55\x1d\x91\x2e\x2e\xce\x8e\x8e\xce\x8e\x18\xd7\x2e\x1a\xb2\x0f\x76\xa6\x6c\x70\x07\xe4\xdb\x25\x47\xfa\x53\x42\x1f\xac\x0f\xde\x8b\xa4\x13\x1c\xa5\xca\x00\x01\x16\x4f\x69\xf3\xfe\xf4\x70\x74\x74\x7d\xe0\xc8\x0e\xd6\x06\xc3\x7c\x81\x87\x6c\xdd\xe1\xac\x60\x3a\xc4\x18\xb8\x8c\x9d\x3d\x97\x8d\xcd\xc1\xf7\xec\x12\x6a\xb2\x1f\x0d\xd4\xd4\x47\xde\x9c\x02\x01\x79\x39\x7a\xf0\x94\x00\xaf\x5a\x70\xd3\xff\xfd\x46\xf7\x0a\xab\x2d\x3c\x02\x98\x74\x60\x45\x53\x4e\x23\x72\xaa\xd1\x50\x46\x39\x9c\x75\xbf\x7f\x72\xb0\x45\xee\x08\x15\xac\x7f\x47\x8f\x75\x09\x7e\x98\xb5\x73\x33\xc5\x5e\x3f\x78\x2f\xc9\xe8\x0c\x7c\x9e\xef\x90\x6e\x96\xee\x73\xd6\xf0\xf6\x1a\xe7\xac\xa3\x80\xb9\x99\xa0\xde\x79\xf9\xf1\xae\xc1\xf1\xf6\x13\x87\xc7\xef\x33\x7a\x1d\xac\x52\xcb\xe6\xc3\x85\xca\x9b\xe4\x3c\x5c\x36\x75\x6f\xc9\x7b\xd9\xa4\xac\x68\xcc\xcd\xd1\x0a\x99\x1a\x5c\x88\xe3\xa3\xdd\x1b\x3f\x76\xec\x2a\xf0\xf1\x30\xe2\xaa\x82\xe2\xf8\xa3\x67\x8f\x07\x3f\xf0\xad\x6a\xa4\x4a\xd9\x34\xf1\xb7\x7b\x9a\xdc\xdd\xd2\x0d\x99\xbb\x0a\xfd\x5a\x7d\x7a\x34\xf9\xfe\x76\xca\x02\x35\xbf\x6c\x41\x89\xc6\x76\xba\xd8\xf3\xbf\x2b\x19\xb5\xa4\x76\xd3\x33\xe4\xc4\x7a\xa6\xee\xe8\xda\x2c\x6f\x8a\x8c\x86\x4f\x41\xf8\xa3\x89\x7c\x19\xfd\x05\x4e\x90\xd4\x35\xb7\xd5\x64\x0b\xf6\xea\xfe\x60\xb8\x56\x3a\x2a\x9b\x43\x2b\x51\x53\x5a\x19\xcf\x93\xfa\xda\xc6\x99\x60\x27\xa9\xae\xf6\xab\x98\xdd\xc4\xe1\x97\xcc\xd3\xf0\x58\xae\x74\x96\xb0\xcc\x49\x1a\xbf\xa1\xe0\xfc\xc5\x63\xfe\x1b\x5b\x9c\xef\x3a\xf9\x56\x42\x93\x5e\xf3\x53\x5e\xa8\x05\xbb\x50\x86\x55\x88\xfc\xe2\xf9\xf0\x89\x66\xb5\xbc\xc8\x4b\xa7\x24\x71\x3f\x30\x42\xa0\x97\xb7\xe0\xf1\x57\xc2\xce\x6d\x87\x49\xf7\xa5\x60\xad\x72\x81\x31\xaa\xec\x61\xcb\x34\xab\x5f\xd4\x98\x23\xe8\x90\xe7\x72\xf8\x70\x8e\xf2\xd5\xa9\x8c\x98\x42\x2a\x1b\x89\x00\xe7\x3b\x87\xf4\x0d\xd7\x74\x0c\x1e\x62\xff\x1a\x8c\xde\x4b\x31\xc4\x17\xef\xe5\x14\x96\xcc\xa2\x4f\xdf\x9c\xac\xb6\xdb\x8b\x5e\xe1\x26\x1f\x54\xc8\xfe\x99\xa2\xf7\x06\xa6\x2d\xe4\x54\x9f\xcf\xe7\x4d\xae\x88\xcf\x78\xad\x95\xf5\x31\x54\xc7\xa0\xf0\x50\x49\x6c\x45\xcc\xa9\xd3\x70\x97\xa8\xef\xd6\xa0\x5b\x79\x5d\xf2\x49\x75\x42\x4a\x75\x61\xe5\xda\x3d\x99\xe7\x93\x06\xe5\x86\xbb\x65\x1b\x13\x99\xe0\xdb\x7a\x4a\x4c\xca\x1b\x33\xc0\x4c\xae\x09\xbe\xda\xa6\xba\xfc\xde\xe1\x52\x0f\x2f\x69\x34\x5f\xba\x71\x71\x5c\x80\x87\x30\x1e\x23\x90\x2d\x43\x31\xa1\x9c\x3f\x51\xd0\xe6\x94\x8f\x9d\x79\xaa\x95\xaf\x6c\x3c\xae\x12\x6a\xe4\x73\x37\xae\xe0\xba\x4a\xc5\x6e\xd7\x0d\xec\x99\x5b\x90\x70\x79\x4c\x3b\xb2\xe8\x09\xfd\xa0\x5e\x78\x7e\x70\x8b\xee\x44\x6b\x64\x68\x7c\xd4\x5f\x07\x1a\xd3\x64\xc2\xe9\x62\x72\x3d\x99\x7d\x1a\x4d\x91\x94\xeb\xeb\x68\xfd\x94\xbf\xb1\x20\xaf\xe3\x27\xdf\x45\x88\x11\x47\x9a\x83\x65\xb8\x13\x8e\xfd\x6b\x12\x53\x42\x14\x06\x71\xb9\xe6\xc6\xb4\x0b\x0d\xd3\x8d\xa2\x23\x1f\x3d\x2d\x92\xcc\x5c\xbe\xb6\x71\xa3\x44\xee\x4c\x7b\x90\xa1\x14\xe9\x23\xd0\x77\xfa\x15\x2e\x6a\xf3\xd8\xf5\x0d\xa8\x17\xbf\xf5\x6e\xcd\x31\xe4\x3c\x69\x39\xe2\x1f\x94\x49\x98\x77\xb5\x4f\xdd\x08\xf2\xac\xb3\x7f\xf0\xce\x6b\x7c\x4b\x66\xe4\x28\xa2\x68\x63\x36\xb2\x78\x52\xf9\xf3\x77\x25\x4e\x27\xec\x76\x60\xe6\x6e\x82\x92\xd8\xab\xf3\x5b\x15\x68\x2f\x09\x77\xf5\xc7\x7b\xd7\xc9\xfd\x19\x70\x76\x5d\x60\x46\xdc\xab\x20\x18\xd5\x67\x7d\xaa\xd8\xea\x9b\x08\xaf\x2b\x0c\x54\x9f\x79\xc8\x9c\xda\x62\xd5\x66\x23\x93\xd5\x66\xc5\x79\x61\x4d\x39\x8d\x2f\xf3\x23\x85\x3d\xe0\xd7\x99\x46\x00\x5a\x78\x50\xa9\xe2\xde\x20\xe6\xae\xb0\xa5\xe9\xd0\x33\xc6\x9a\x24\xed\x0a\xb9\x35\x21\xff\x17\x65\x4f\xef\x59\x9c\x8b\x80\xce\x57\xd2\xe5\x5f\xe2\x1a\xd5\x5a\x35\xa7\xcf\x12\x75\x6b\xc2\xcd\xb2\x56\x53\x6b\xdc\xef\x4f\xf6\xb6\x90\xa5\x98\x47\x85\x05\xd8\x11\x98\xa0\x98\x4e\xab\x13\xd3\xfd\xce\x4f\xf9\x55\x65\x96\x2f\xef\xbb\xf8\xb3\xdc\xe7\x7d\xff\x78\x55\x73\xe6\x2f\x96\xd4\x9a\xad\xc3\x96\x2a\x9d\x99\xcb\xa4\x44\x7a\x2c\x2e\x12\xf4\x0c\x46\xab\x65\x9d\x4d\xd7\x91\x97\xb6\x7f\xbb\x62\xd2\x98\xce\x6e\x1d\x26\xcd\x21\x0d\x9d\xf9\xd9\x8a\x19\x1b\x5f\x3e\x2b\x60\xe3\xa6\x25\x46\x9e\xc9\x33\x5f\xa5\x9d\x8f\x31\xb4\xd6\xb5\xde\x75\xac\x9d\x9a\x49\xc5\xb4\x34\x53\xae\xbf\x12\xb0\xca\x70\xee\x18\xdd\xb6\x5d\x4e\x4a\x1e\xd5\xfb\xad\xe5\x2a\x14\xa6\x7a\x78\xbf\x8b\x05\x29\x9c\xe5\xf4\x82\xce\xae\x7a\x69\x2c\x8c\xf1\x7b\xda\x16\xea\xd0\x00\xd6\xcc\x82\x89\x29\x7b\x34\x90\x87\xa8\xc3\xa1\xaf\x21\x7d\x3a\x1e\x23\xf8\x0c\xec\x1b\x71\x9f\x84\x0a\x5f\xe1\xde\x3a\x8e\x0a\xcd\x7e\x8b\xd5\x30\xf3\xc9\x5c\xf7\x0d\x2b\x89\xb8\xf6\x28\x33\x0a\x6b\xb9\x33\xc8\xce\x82\x82\x9d\x78\x1f\x69\xcf\x6e\xd7\x1b\x1f\xda\xbe\xc4\xc5\x0a\x74\x7e\x9c\x51\x33\xe7\x46\xf5\xbd\x79\xfe\x40\x9f\x77\x3d\xde\x73\xdf\xc9\xae\xfa\xb3\xb6\x94\x61\x71\x6d\xe5\x2c\xdd\xc8\xeb\x44\x28\x97\xce\x7c\x88\x5e\x0a\x06\xf1\xeb\x16\xc3\x0b\x1d\x9d\x1b\xd5\xed\x37\x8b\x3e\xb6\x9c\x0f\x0b\xde\x5d\xbc\x7e\x4e\x15\xad\xee\xe1\x7c\x71\xd4\x91\xb7\x52\x9c\x19\xd2\x98\x81\xb1\xf0\x06\x99\x36\x5f\xcd\x32\x9d\xc9\xef\xe9\x7b\x41\xbf\x30\x56\xba\x17\x36\x30\x27\xe0\x3f\x2d\xb3\x10\x68\x34\xff\xa3\xa3\xdc\xbc\x39\x26\xa6\xc5\x1a\xb6\xfb\x19\x9e\xf9\xcc\x40\xbc\x72\xbb\x87\x9e\xa3\x72\x64\xec\xd9\xfb\xaf\x18\xbb\x8c\x2f\xc1\x50\xa4\x28\xb2\x78\xb1\x84\x85\xe3\xd2\xf2\xd8\xef\x44\xd9\xb2\x8a\xa6\x74\xf5\x56\x7b\x51\x25\x57\xe9\xb8\x33\xe4\x10\xaa\x10\xa5\xf3\x93\x82\xb8\x29\x69\xd0\x12\x9f\xb9\x19\x96\xc3\x44\xb8\x3b\xdf\x33\x27\x65\xdf\x67\xff\x92\xb0\xb2\xd8\xf5\xb2\x71\xc3\x75\xeb\xaa\xaf\xc6\x24\x5d\x6e\xc2\x4b\x1b\xce\xd6\x61\xba\xf0\x0a\xb0\x92\xca\x87\xf9\x94\x1f\xb0\xfd\xba\x3d\x9a\x03\x80\x23\x53\x97\xf3\xfe\xc3\x3d\x9b\xfe\xef\x42\x0f\x0e\xc2\xfb\xe1\x5c\x4b\x01\x1b\x48\x77\xa9\x84\x6e\xd6\x00\x36\x2f\x69\x37\x3a\xc7\x04\x45\x48\x70\x5e\x8f\x63\xaa\x22\xa4\xc3\xf1\x9d\x52\x57\xce\xa8\x13\x4c\x2a\x41\xbd\x17\x0e\x36\xca\x65\x02\x28\x63\xe8\x63\x6a\x73\x7b\x96\xb0\x1b\xc8\x93\x78\xc5\x63\x60\x07\x29\xce\x55\x84\x30\x6e\x20\x67\x67\x02\xb1\x82\x01\x49\x57\x02\xaf\x54\x7a\x1b\xb3\x10\xbb\x7e\x30\xb1\x1e\xbf\x52\xf8\x68\xc6\xfe\xba\x73\x35\xce\x29\xca\x07\x56\x1f\x85\xc4\x3f\xbf\xe1\xd9\xaa\x52\x76\xd1\x4b\xab\x71\x3e\x87\x28\xbf\x70\x86\x99\x46\x4d\x05\xba\xdd\x3a\x7f\x74\x25\xfe\xb4\x4d\xdd\xe0\xbc\x07\x51\xae\x3a\x29\xd1\xef\x9f\xd7\x7d\x47\xbb\x43\x3f\x0e\x34\x2c\x2e\x47\xf8\x7e\xdc\xfb\x9b\xf2\xef\xab\x6a\x4d\xa4\xfb\x14\x78\x79\x09\x80\xde\x2b\xc4\x98\x2d\xe8\xc3\x2d\x99\x3b\x37\xbf\xfc\xf2\xb7\x0f\xd1\x2e\x6a\xaf\xaf\xd9\x7e\xc3\xe5\x17\xbc\x3d\x60\xd3\x7f\x3e\xec\x29\x10\x1c\x22\xcb\x7d\xbb\x8d\x85\x01\xed\x41\xa3\x9e\xcc\xc7\x7f\x62\xac\xc9\x98\xfe\x21\xf6\x66\x92\x15\xb5\x96\xde\x96\x7e\x12\x4e\xb5\x49\xc6\xfb\x14\x06\xd3\x2b\x48\xf8\xd0\xac\x77\x01\xfe\x6e\x7c\x68\x41\x8c\xc1\x8e\x2f\xd4\xe5\x37\x05\xb8\xbd\x6b\xdf\x9c\xe7\x0a\x78\xa7\xb2\x79\x26\x5e\x12\x0b\x8f\x1a\x61\xb5\x7e\xe0\xee\x12\xe7\xbe\xd8\xc9\x6e\x29\xc8\x79\xf5\x41\xe1\x63\x08\x30\x84\x36\xc2\xc9\x74\x42\xfd\x76\x4b\x1f\x4a\x96\x7c\x6b\x0d\x29\xac\x00\x46\x6c\xad\x4d\x1a\xda\x98\x67\x08\x16\xd9\x4d\xc4\x3c\x95\x86\x58\xdf\xda\x0c\x88\xa3\x35\x16\x7c\xc2\xa6\x33\xef\x60\xe6\x9b\x1c\x3d\x12\x86\xb3\xed\x8b\xc6\x3e\x24\x6c\x3d\xa8\xa2\x0b\x0c\x0c\x8e\xc8\x7e\xd7\x29\x0f\x95\x44\xd9\x53\x37\x04\xbb\x32\x5b\xd7\x36\x3f\xff\x1a\x68\xd9\xa0\x95\x95\x4c\x27\xe6\x1e\x68\xeb\x23\x18\x2f\x35\xc4\x6f\x3d\x42\x1e\xe8\x6d\x3d\x85\x40\xd4\xba\x73\xbf\x18\x1f\xf0\x9c\x4c\x77\x4f\xea\xff\x24\xff\x11\x41\x94\x74\xc8\x09\xfa\x99\x21\xa4\x5b\x5a\x92\x8d\x91\x05\xcc\x68\x6f\x6e\x4c\x6f\x6c\x4c\xf7\xd5\x38\x25\xb4\xd9\xf3\x97\xc5\x6e\x23\x52\x1b\x3d\x4c\x25\x79\x8b\xbf\xb8\x53\xa7\x0c\x0d\xbf\x11\x4b\xc8\x2c\x7e\x31\xd0\x1a\x44\x55\x85\xf2\xb2\x94\x51\x2d\x03\x9b\xd7\xef\x69\x04\xa1\xb0\x37\xd7\x3d\x21\x25\x93\x28\x04\x77\xf2\x52\x8f\xd2\x12\xf4\xe9\x63\x07\x29\x03\xb2\x54\x4a\xd3\xba\x77\x08\xb4\x06\xa8\x28\xb7\x35\x50\x78\x0b\x9f\xcc\xac\x63\x27\x4e\x20\xf6\x5d\x12\x6b\x71\xb5\x37\xea\xab\x6d\xb3\xe9\xfc\x22\x93\x06\x4a\x06\x08\xe1\xa6\x3e\xa6\x07\x62\xa9\xe3\xa3\x12\x1a\x17\x8d\xfd\x69\xc4\x83\x83\x03\xd4\x11\x3f\xb6\xa7\xf5\xaf\x57\x35\xf6\xd5\x34\xd8\x69\x59\xda\x44\xba\x6b\x0f\x9e\xe3\x4d\xca\x33\xac\xbf\xea\xca\x35\x1a\x4c\xad\xfc\xf8\x52\xd1\xb9\xab\xf7\x99\xd2\x36\x0d\x2e\x5a\xf0\x5b\x3f\x64\x1b\x6a\xd1\xbf\x35\xdb\xf6\x39\xcc\xf6\x05\xbf\x5c\x1d\x57\x3c\xf4\xae\x72\x71\x5b\x67\x64\xb9\x97\xac\xea\xb7\x2d\xe8\x37\xa3\x7b\xf2\x21\x1d\x9f\x3a\xec\xb3\x85\x47\xda\x26\x43\x72\x8e\x7a\x88\xcd\x73\x46\x45\xa2\xf8\xb9\xc1\xe2\x3b\x5e\xbc\x13\x46\x11\xe5\x19\x7a\x8e\x03\x6b\xca\x73\xfe\xde\x5f\x43\x03\x7b\x1b\x31\xf1\xea\x0a\xd7\x82\x81\xdb\xb9\xd5\x72\x3c\x53\xd6\x42\xb3\x4e\xd7\xd7\x63\x77\x20\x86\xf6\x1d\x67\x9e\x26\xa8\x6c\x29\x49\xe9\x62\xe5\x4f\x67\x1b\x11\x1e\xe7\x03\x8d\x7a\x41\xae\xe5\x9e\x39\xc2\x71\x26\x52\x7a\xbc\xc1\xe4\x77\xf6\xd6\x86\xbf\xb0\x29\xdb\xce\x6a\x42\x16\x10\x89\x0a\xcd\x32\xa3\xae\xba\xd7\xfd\x86\x04\x9f\xa7\xdf\x3f\xa4\xf7\xe0\x82\xb6\x47\x04\xed\x39\x4f\x5d\x27\xa4\x16\x08\x9b\x23\x19\x12\x85\xf5\xd2\x7b\x90\xc5\x44\xd6\xac\x57\xd4\x91\x78\x0f\x08\xc3\xa3\x8f\xa0\x89\xbe\x1a\x31\x6b\x1e\x73\xc3\x9a\x25\x7f\x3b\x97\xee\x52\x3b\xd6\xa0\x80\x0f\x71\xe1\xe2\x63\x3a\x76\x50\x51\xf9\x08\x9a\x96\xd7\x56\x1d\x52\x32\xf4\x4c\x26\x51\xfc\xcb\x3f\x24\x43\x8d\xe0\x2f\x2d\x28\x85\xdc\x7b\x0f\x5c\x86\x5b\x76\x9e\x9d\xba\xcc\x88\xc4\xe7\x0b\x2b\xfa\xf1\x92\xeb\x18\x69\x05\xd4\x8c\x75\xeb\x8c\x9d\x70\x2d\xe0\xaa\x72\xda\xfd\x23\xfd\xf0\x3f\x7f\xf2\x7b\xb2\x7b\xac\xac\x0c\x5d\xc8\x5a\x70\xc0\xcf\xe2\x74\x4a\xc4\xbc\x46\x65\xbe\x54\x8d\x8e\x9a\x21\x99\x9e\x15\xf6\xf0\xd6\x09\xae\x6b\xcb\xa8\x49\x5e\x79\xa6\x97\x1c\xb9\x22\x1f\xbe\xda\x37\x85\x0a\xdd\x4c\x08\x5a\xbf\xf8\x06\xb2\xae\xac\x9b\x71\x4b\xf6\xb5\xe5\x23\x13\xf8\xdc\x5b\x3b\x75\x65\x47\x35\x89\x29\x69\xd6\x4a\xa4\xed\x05\xaa\xdf\x86\xff\x90\x77\xf9\xb1\x7f\xe3\x26\x0d\x2f\x75\xce\xb1\x9a\x30\xc1\x9d\x52\x96\xd0\x05\x8c\x72\x90\x38\x96\xb7\x90\x46\xa3\xd9\x67\xb7\x24\xee\xf8\xcc\xbb\x1e\x54\xd0\x41\x23\x6d\x6c\x18\xe5\x4e\xcb\x3a\xed\xf6\x16\x17\x54\xaa\xba\xd7\xc6\xb7\xdb\xb6\xd7\x62\x79\x7f\x50\xdb\x23\xaa\x89\x42\x71\xf0\x87\x5a\xc9\xc5\x9a\x69\xbc\xf7\x84\x4e\x6a\xde\xdf\xee\x10\x62\x42\xe9\xff\xd6\x0f\x3e\x95\x4c\x9d\xdb\x98\x98\x29\xe7\x5c\x5d\x29\xa5\xbd\x79\xa3\xbe\x3b\xa5\xa8\xee\xc0\xfe\xb0\xa2\x1f\x77\x83\x89\xec\x5e\x47\xa7\x15\x25\x56\x8b\x30\x1c\x32\xc1\xaa\x16\x85\x7a\x57\xe2\x6e\x71\x23\x6a\xd8\x90\x79\x25\xfa\xf5\xdf\x83\x1a\xd3\x0c\x9b\x09\xaa\x04\xfa\x82\x51\xa5\x1f\x1e\x41\x27\xd0\xdf\x4f\x02\x1a\xe2\x09\x04\x1b\x0a\x3b\xf8\xed\x93\x30\x75\x28\x31\x61\x0d\x7e\xba\xca\x88\xef\x18\x18\x61\x7a\x58\x4e\xb3\xbc\x26\xae\x66\x83\x27\x73\x48\xd4\xe2\xee\x95\xc5\xbf\xbd\xfe\xbe\x22\x59\x1d\xed\x03\xed\xcb\xe4\x76\x5d\x35\x98\xf9\xd9\xae\x12\x91\x95\xd4\xd7\x93\x70\x7a\x89\x0b\xb5\x00\x5c\x80\x5f\x17\x33\xf0\xff\xe3\x37\x1d\x1d\x01\x2b\xf5\xec\x40\xc2\xea\x2f\xef\x0e\x29\x5f\xe9\x4e\x40\x22\xd2\x4e\xb4\x88\x09\x50\x92\xc4\x7c\x71\x79\x49\xe8\x7b\x3a\x0e\x27\x5f\xf3\x47\x22\x71\x9a\xc0\x60\x0c\x1d\xd3\x7f\x35\xff\x5a\xcf\xa7\xe3\x5d\xfb\x97\x5c\x49\x40\x90\x31\x39\x85\x2f\x10\xe0\x57\x47\xfe\x90\x94\x8f\xec\xee\xea\x82\x53\xf7\x46\xab\xbd\x05\xdc\xac\x27\x82\xb6\x58\xc1\xe0\x72\x15\x63\x3f\x04\x18\x60\xd3\x00\xaa\xff\x5f\x83\x59\x0c\xd8\x01\x0a\x02\xdd\x81\x17\x64\x52\x64\x77\xc9\xca\xc9\xd6\x48\x1c\xf0\x1f\x97\xef\x01\x00\xff\xa3\x20\xfb\xe3\xe3\x01\x01\xa4\x27\x0f\xad\xef\xbf\x9e\x34\x28\x7d\x4c\xaf\x47\x8d\x59\xbb\xd3\x03\x3b\xc5\x6a\xc6\x3c\x1f\x6a\x69\xc2\x30\xc9\x45\xd4\x86\xd1\x64\xb5\x4e\xa0\xd2\xef\xf2\x3f\xf2\xc8\xc8\x70\x1d\x76\xb1\x21\x62\x4f\xe8\x55\x93\x25\x96\xeb\x4f\x64\x8b\x12\x1b\x72\xd3\x46\x5b\xdc\xf6\xe6\x5b\xf2\x00\x0a\x03\xf2\xcc\x72\x96\x39\xe3\xf1\x2c\x29\x6c\xde\x6f\x62\x35\x94\x15\xc4\x27\x6f\x28\xd5\xa4\x11\x38\xb9\x8a\x53\x2c\x07\xcc\x4f\xe5\x07\x64\xe7\x79\xfc\xed\x06\x28\x54\xad\xd4\xcd\x53\xd8\x51\x07\x5b\x56\xcb\x06\x45\x4a\xe2\xcb\x9a\xf6\x8a\xe2\x93\x8b\x8a\x35\x69\x5c\xa4\x1b\xc3\xa4\x5d\xa1\xe6\x03\x65\x0a\x96\xed\xf9\xbc\x1f\xe7\xcc\xd7\x17\xb5\x9b\x22\x8f\x35\xeb\xb2\xb4\x2f\xb5\x95\xaa\x83\x2d\xfb\x45\x26\xcc\x74\x37\x2a\x56\x24\xbc\x5e\xa2\xc4\x55\xf2\x88\xa3\xf1\x1e\x55\xed\x6a\xe3\x4d\xca\x90\x52\xad\xaf\x05\xde\x6f\x38\x75\x4a\x86\x98\x8a\x74\x3f\x63\xbd\xa7\x4c\x73\xe3\xfa\x9b\x97\x7f\xb7\x86\x76\x24\x2b\x4d\x1b\xba\x38\xff\x30\x00\x8b\x6b\x6c\x68\x1b\xf5\x74\x85\xd6\x35\x7e\xff\xed\xfa\xfd\x5b\x24\x51\x03\x9d\xc2\x02\x61\xbc\x66\x0e\xa1\x55\x8f\x39\x8a\x47\x53\x8a\x35\xfc\xe2\x25\x47\xbb\x52\x49\xcb\x5b\x53\x4b\x9d\xdc\xf2\x08\x17\x7d\xc3\x23\xee\xea\xdf\xaf\xa2\xca\xa4\xcd\xee\x3d\x98\x9c\xb9\xc3\xbd\x14\xd6\xb4\x99\x50\x86\xdf\x36\xb5\x90\x0c\xab\x6f\x3b\xc0\x37\x7c\xe1\x15\x7a\xfb\x4a\x22\x75\x61\xd7\x55\x25\xfd\x35\xcf\xa4\xc4\xce\x6f\x9f\x6f\x8a\xd9\xf3\xd5\x1a\xd8\x16\xcf\x85\x67\x42\xad\x8c\x90\x60\x4f\xaa\x71\xb4\x8a\xfc\x33\x6a\x62\xfb\x8a\x99\xe8\xae\x4a\xfe\xdb\xcb\x5f\x1d\x5c\x4b\x2e\xb1\x28\xd2\x7b\xf7\x1e\x54\xa7\x7f\x80\x80\x50\x4c\x44\x8a\x56\xce\x67\xa4\x81\x75\xab\xd8\x84\x8f\x2d\x57\xa7\x9b\x73\xfb\xd2\x4a\x8d\xca\xa2\xc6\x13\x7a\xc8\xe3\x75\xba\x92\x29\x44\x56\x32\x6d\xad\x35\x1b\x9f\x58\x88\xe5\x96\x3d\x91\xbf\xf6\xd7\x42\x67\x5d\x71\x75\x83\xdf\x81\xf8\xc0\x92\x69\x42\x5c\x61\x8a\xa8\x5e\x20\xc8\x1e\xc3\x4c\x46\xea\x89\xde\xff\xd2\xed\xcb\x23\xe8\xcc\xcb\x8b\xbe\xb3\x06\xee\x2f\x82\x43\xe0\x90\x21\x0a\x0e\x76\xab\x22\x39\x29\xa4\xbb\xba\x3b\x3d\x73\xa8\x00\x08\x04\x12\x90\x4a\xca\xeb\xc6\x94\xd2\xa0\x75\x1c\x7b\xc1\x09\x29\xf8\x47\xa3\x42\xe2\x1c\x53\x6a\x6f\xed\xe1\x74\x90\x64\x51\x7a\xce\x21\x6e\x06\x04\x7f\xba\xda\xab\x74\x9c\x0e\x96\x72\xf5\x72\x9a\x4e\xb4\x9d\x23\x8f\xcd\x0e\x40\x39\xc9\xf3\x86\xf4\xcf\xfc\x0f\x4c\x4f\xa8\x44\x98\x0e\x00\x00" + +func font_fontello_woff_gz_bytes() ([]byte, error) { + return bindata_read( + _font_fontello_woff_gz, + "font/fontello.woff.gz", + ) +} + +func font_fontello_woff_gz() (*asset, error) { + bytes, err := font_fontello_woff_gz_bytes() + if err != nil { + return nil, err + } + + info := bindata_file_info{name: "font/fontello.woff.gz", size: 3701, mode: os.FileMode(436), modTime: time.Unix(1432518658, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _index_html_gz = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\x65\x50\xc1\x4e\xc3\x30\x0c\xfd\x95\xd0\xeb\x68\x23\x6e\x1c\x92\x72\xd8\x40\xe2\x80\x40\x30\x0e\x3b\x66\x89\xdb\x1a\xdc\xa4\x8a\xcd\xa6\x4a\x7c\x3c\xd9\x3a\x24\x24\x2e\xd6\x7b\xcf\xcf\x4f\x7a\x36\x57\x9b\xe7\xf5\x76\xf7\x72\xaf\x06\x19\xa9\x35\xa7\xa9\xc8\xc5\xde\x42\x2c\x0c\x5c\x68\xcd\x08\xe2\x94\x1f\x5c\x66\x10\xfb\xbe\x7d\xa8\x6f\x2f\x5a\x74\x23\xd8\x03\xc2\x71\x4a\x59\x94\x4f\x51\x20\x8a\xad\x8e\x18\x64\xb0\x01\x0e\xe8\xa1\x3e\x93\x6b\x85\x11\x05\x1d\xd5\xec\x1d\x81\xbd\xa9\x5a\x23\x28\x04\xed\xe3\xeb\xda\xe8\x05\x1a\xc2\xf8\xa9\x86\x0c\x9d\xad\xb4\xee\x4a\x1a\x37\x7d\x4a\x3d\x81\x9b\x90\x1b\x9f\x46\xed\x99\xef\x3a\x37\x22\xcd\xf6\xe9\xb4\x87\x9c\x9d\x7c\x6f\x72\xc2\xb0\x7a\x73\x91\x57\x45\x4d\x95\xca\x40\x96\x65\x26\xe0\x01\x40\xfe\x06\xef\xbf\x62\x20\x68\x4a\xce\x3f\x93\x5e\xca\xee\x53\x98\x5b\xc3\x3e\xe3\x24\x8a\xb3\xff\x3d\xf9\xe0\x62\x59\xe4\x02\x16\x97\x3e\xff\xec\x07\xf7\x87\x06\xb5\x43\x01\x00\x00" + +func index_html_gz_bytes() ([]byte, error) { + return bindata_read( + _index_html_gz, + "index.html.gz", + ) +} + +func index_html_gz() (*asset, error) { + bytes, err := index_html_gz_bytes() + if err != nil { + return nil, err + } + + info := bindata_file_info{name: "index.html.gz", size: 241, mode: os.FileMode(436), modTime: time.Unix(1432518658, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if (err != nil) { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "bundle.css.gz": bundle_css_gz, + "bundle.js.gz": bundle_js_gz, + "config.default.toml": config_default_toml, + "font/fontello.eot.gz": font_fontello_eot_gz, + "font/fontello.svg.gz": font_fontello_svg_gz, + "font/fontello.ttf.gz": font_fontello_ttf_gz, + "font/fontello.woff.gz": font_fontello_woff_gz, + "index.html.gz": index_html_gz, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type _bintree_t struct { + Func func() (*asset, error) + Children map[string]*_bintree_t +} +var _bintree = &_bintree_t{nil, map[string]*_bintree_t{ + "bundle.css.gz": &_bintree_t{bundle_css_gz, map[string]*_bintree_t{ + }}, + "bundle.js.gz": &_bintree_t{bundle_js_gz, map[string]*_bintree_t{ + }}, + "config.default.toml": &_bintree_t{config_default_toml, map[string]*_bintree_t{ + }}, + "font": &_bintree_t{nil, map[string]*_bintree_t{ + "fontello.eot.gz": &_bintree_t{font_fontello_eot_gz, map[string]*_bintree_t{ + }}, + "fontello.svg.gz": &_bintree_t{font_fontello_svg_gz, map[string]*_bintree_t{ + }}, + "fontello.ttf.gz": &_bintree_t{font_fontello_ttf_gz, map[string]*_bintree_t{ + }}, + "fontello.woff.gz": &_bintree_t{font_fontello_woff_gz, map[string]*_bintree_t{ + }}, + }}, + "index.html.gz": &_bintree_t{index_html_gz, map[string]*_bintree_t{ + }}, +}} + +// Restore an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, path.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// Restore assets under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + if err != nil { // File + return RestoreAsset(dir, name) + } else { // Dir + for _, child := range children { + err = RestoreAssets(dir, path.Join(name, child)) + if err != nil { + return err + } + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} + diff --git a/client/gulpfile.js b/client/gulpfile.js index 8a46c6f1..0c7be449 100644 --- a/client/gulpfile.js +++ b/client/gulpfile.js @@ -79,21 +79,26 @@ gulp.task('fonts', function() { .pipe(gulp.dest('dist/font')); }); +gulp.task('config', function() { + return gulp.src('../config.default.toml') + .pipe(gulp.dest('dist/gz')); +}); + gulp.task('gzip', ['html', 'css', 'js', 'fonts'], function() { - return gulp.src('dist/**/!(*.gz)') + return gulp.src(['dist/**/!(*.gz)', '!dist/{gz,gz/**}']) .pipe(gzip()) .pipe(gulp.dest('dist/gz')); }); function bindata(cb) { if (argv.production) { - exec('go-bindata -nomemcopy -nocompress -pkg server -o ../server/bindata.go -prefix "dist/gz" dist/gz/...', cb); + exec('go-bindata -nomemcopy -nocompress -pkg assets -o ../assets/bindata.go -prefix "dist/gz" dist/gz/...', cb); } else { - exec('go-bindata -debug -pkg server -o ../server/bindata.go -prefix "dist/gz" dist/...', cb); + exec('go-bindata -debug -pkg assets -o ../assets/bindata.go -prefix "dist/gz" dist/gz/...', cb); } } -gulp.task('bindata', ['gzip'], function(cb) { +gulp.task('bindata', ['gzip', 'config'], function(cb) { bindata(cb); }); @@ -114,4 +119,4 @@ gulp.task('watch', ['default'], function() { return js(true); }); -gulp.task('default', ['html', 'css', 'js', 'fonts', 'gzip', 'bindata']); \ No newline at end of file +gulp.task('default', ['html', 'css', 'js', 'fonts', 'config', 'gzip', 'bindata']); \ No newline at end of file diff --git a/commands/config.go b/commands/config.go new file mode 100644 index 00000000..5163060b --- /dev/null +++ b/commands/config.go @@ -0,0 +1,48 @@ +package commands + +import ( + "log" + "os" + "os/exec" + "path" + "syscall" + + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/spf13/cobra" + + "github.com/khlieng/name_pending/storage" +) + +var ( + editors = []string{"nano", "notepad", "vi", "emacs"} + + configCmd = &cobra.Command{ + Use: "config", + Short: "Edit config file", + Run: func(cmd *cobra.Command, _ []string) { + if editor := findEditor(); editor != "" { + args := []string{editor, path.Join(storage.AppDir, "config.toml")} + syscall.Exec(editor, args, os.Environ()) + } else { + log.Println("Unable to locate editor") + } + }, + } +) + +func findEditor() string { + if editor := os.Getenv("EDITOR"); editor != "" { + editor, err := exec.LookPath(editor) + if err == nil { + return editor + } + } + + for _, editor := range editors { + editor, err := exec.LookPath(editor) + if err == nil { + return editor + } + } + + return "" +} diff --git a/commands/name_pending.go b/commands/name_pending.go index 794c44fc..cc4dc2dd 100644 --- a/commands/name_pending.go +++ b/commands/name_pending.go @@ -2,6 +2,7 @@ package commands import ( "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/spf13/cobra" + "github.com/khlieng/name_pending/Godeps/_workspace/src/github.com/spf13/viper" "github.com/khlieng/name_pending/server" "github.com/khlieng/name_pending/storage" @@ -13,17 +14,22 @@ var ( Short: "Web-based IRC client in Go.", Run: func(cmd *cobra.Command, args []string) { storage.Initialize() - server.Run(port) + server.Run(viper.GetInt("port")) }, } - - port int ) func init() { rootCmd.AddCommand(clearCmd) + rootCmd.AddCommand(configCmd) - rootCmd.Flags().IntVarP(&port, "port", "p", 1337, "port to listen on") + rootCmd.Flags().IntP("port", "p", 1337, "port to listen on") + + viper.SetConfigName("config") + viper.AddConfigPath(storage.AppDir) + viper.ReadInConfig() + + viper.BindPFlag("port", rootCmd.Flags().Lookup("port")) } func Execute() { diff --git a/config.default.toml b/config.default.toml new file mode 100644 index 00000000..e2b1fd0f --- /dev/null +++ b/config.default.toml @@ -0,0 +1 @@ +port = 1337 \ No newline at end of file diff --git a/main.go b/main.go index 6f85b06a..27926c4c 100644 --- a/main.go +++ b/main.go @@ -1,9 +1,34 @@ package main import ( + "io/ioutil" + "log" + "os" + "path" + + "github.com/khlieng/name_pending/assets" "github.com/khlieng/name_pending/commands" + "github.com/khlieng/name_pending/storage" ) func main() { + initConfig() commands.Execute() } + +func initConfig() { + configPath := path.Join(storage.AppDir, "config.toml") + + if _, err := os.Stat(configPath); os.IsNotExist(err) { + config, err := assets.Asset("config.default.toml") + if err != nil { + log.Println(err) + return + } + + err = ioutil.WriteFile(configPath, config, 0600) + if err != nil { + log.Println(err) + } + } +} diff --git a/server/bindata.go b/server/bindata.go deleted file mode 100644 index eae2cfda..00000000 --- a/server/bindata.go +++ /dev/null @@ -1,361 +0,0 @@ -package server - -import ( - "fmt" - "reflect" - "strings" - "unsafe" - "os" - "time" - "io/ioutil" - "path" - "path/filepath" -) - -func bindata_read(data, name string) ([]byte, error) { - var empty [0]byte - sx := (*reflect.StringHeader)(unsafe.Pointer(&data)) - b := empty[:] - bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) - bx.Data = sx.Data - bx.Len = len(data) - bx.Cap = bx.Len - return b, nil -} - -type asset struct { - bytes []byte - info os.FileInfo -} - -type bindata_file_info struct { - name string - size int64 - mode os.FileMode - modTime time.Time -} - -func (fi bindata_file_info) Name() string { - return fi.name -} -func (fi bindata_file_info) Size() int64 { - return fi.size -} -func (fi bindata_file_info) Mode() os.FileMode { - return fi.mode -} -func (fi bindata_file_info) ModTime() time.Time { - return fi.modTime -} -func (fi bindata_file_info) IsDir() bool { - return false -} -func (fi bindata_file_info) Sys() interface{} { - return nil -} - -var _bundle_css_gz = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x0b\xad\x58\x6d\x6f\xe3\x36\x0c\xfe\x2b\xd9\x15\x43\xaf\x87\x38\x73\x92\xa6\x2f\x36\x6e\x2f\xbd\xa2\xdf\xf6\x69\x1f\x6f\x1d\x20\xdb\x4a\xa2\x55\xb6\x0c\x49\x6e\x9b\x33\xf2\xdf\x47\x49\x96\x2d\x39\x72\x7b\x1b\xd6\x00\xad\x23\x51\x24\xf5\x90\x7c\x48\x37\x6b\xa4\x64\xd5\x9c\x54\x75\x23\xdb\x8c\xf1\x02\xf3\xa4\x62\x15\x4e\x59\x23\x29\xa9\x70\x12\x1f\x3f\xcd\xc9\xd7\x9c\x22\x21\x3e\x7d\xfe\x30\x23\x39\xab\xa2\x0f\x8f\x49\x86\xb7\x8c\x63\xbb\xf3\xd7\x67\xbd\x6e\x97\xdb\x12\xf1\x1d\xa9\xe0\xec\x22\xdf\x23\x19\x49\x22\x29\x9e\x77\xcf\xac\x26\xf9\x7c\x51\x62\x21\xd0\x0e\xb7\x2f\x7b\x22\x71\x24\x6a\x94\x63\xb0\xfb\xc2\x51\x7d\xfc\x75\xcb\x2a\x19\x6d\x61\xa5\xed\x9e\x4a\x42\x0f\x89\x7a\xc6\x94\xb2\x54\xf0\x3c\x69\x38\xfd\xa8\x16\x7e\xb2\xab\x0b\xcc\xe4\x2f\xd7\xeb\x4b\xf8\xb9\xbd\xba\xf8\x0e\x99\x33\x82\xb7\xe4\xf5\x02\xdc\x2d\x91\xfc\x78\x8e\xcb\x0c\x17\x05\x2e\x22\x56\xe3\x4a\x1e\x6a\x7c\x7e\x31\x3f\x55\xf0\xc2\xb6\xdb\xc1\x8a\x3d\xab\x56\x83\xe2\x52\x06\xa4\x25\x6f\xf0\xa4\x01\xf1\xbc\x1b\x3c\xb4\xab\xfd\x51\xd8\x3d\xbf\x48\x35\x28\x2f\x98\xec\xf6\x32\xb9\x8c\x63\xf3\x5d\xc8\x03\x55\x08\x82\x20\x3d\x4e\x86\x2b\x1c\xad\x20\xca\x27\x5a\x4f\xec\x8a\x1a\xa3\x27\x93\x2c\x05\x11\x35\x45\x87\x84\x54\x2a\x67\xa2\x8c\xb2\xfc\x29\x95\xf8\x55\x46\x05\xce\x19\x47\x92\xb0\x0a\x36\xf7\x98\x13\x99\xbe\x90\x42\xee\x93\x25\x2e\x53\x93\x26\x11\xd7\x2a\x17\x2b\x58\xd1\x67\x10\x25\xbb\x2a\xc9\x21\x0e\x98\x1b\xab\xcf\x88\x13\x54\x49\xeb\x89\x96\x92\x1c\x55\x42\x21\x63\x5c\xd0\x86\xf7\xc6\x3b\x47\x37\xc5\x5b\xa3\xfa\xb8\xd0\x97\xce\xd9\xce\x5e\x3b\x57\x57\x05\xa5\xe7\x7f\xe2\x9b\x38\x3e\xef\x04\xe0\xf2\xa4\x16\x44\x04\xa5\x96\x56\x4a\x60\xc4\xf3\x7d\x50\x66\x65\x65\x1a\x01\xb5\x14\x92\x58\xbb\x12\x61\x43\x97\x56\x84\xb2\x1d\x54\x62\x50\x66\x63\x65\x4a\x5c\x35\x41\x89\x2b\x2b\x51\xd3\x26\x6c\xe7\xda\x4a\xe4\xa8\xca\x31\x0d\xca\xdc\x9c\x1f\x3f\xb5\x35\x2a\x0a\x52\xed\x92\x38\xcd\xd8\x6b\x24\xc8\x37\xf5\xc5\xf0\x45\x04\x2b\xc7\x8c\x15\x07\x2f\x91\xee\x39\x23\xc5\xec\x0f\x88\xd1\xec\x77\x56\xb1\x79\x09\xbf\x74\x99\xa7\x19\xca\x9f\x76\x9c\x35\x55\x91\x9c\x6d\x63\xf5\x39\x1a\xfa\x51\xc7\x93\xe5\x55\xfd\x3a\x9b\x3c\x7c\xcc\x34\x5f\x39\xa2\xb0\x2f\x01\x46\xc8\xb1\xb9\x00\x79\x88\x0c\x27\xdb\x34\x6f\xb8\x60\x3c\xa9\x19\x51\x49\x74\xac\x5b\x2f\x3d\x16\x9b\xe3\x42\xa2\x8c\x12\x21\xdb\x9a\x09\xa2\xd3\x13\xd8\x00\x17\xa9\xce\x97\x38\x05\x96\xd2\x57\x05\x63\x25\x3c\x98\x94\x5d\xc5\x71\xfd\xea\xb9\xbf\x5a\xad\xd2\x9c\x51\xb0\x74\xf6\xf0\xf0\x90\xba\xf7\x0f\xfa\xa5\xcd\x46\x0a\x5d\x04\xfe\xf0\xc1\x38\xca\x04\xa3\x8d\xc4\xda\xf0\x46\x9b\x31\xb6\xf5\x73\x57\x31\x71\xfc\x63\xca\x9e\x31\xdf\x52\xf6\x92\xa0\x46\x32\xa0\x57\x56\x55\x38\x97\xf3\x85\x20\x05\xd4\x9d\x06\x47\x8c\xef\x64\xaf\xd1\x5f\x7a\x56\xf7\xf1\x5c\x03\x84\xcb\x0d\xd8\x18\x21\x36\x88\x26\x40\x19\x32\xca\xf7\x84\x16\x1d\xaf\x47\x9d\xc2\x25\xf8\xe6\x0a\xee\x95\x73\xad\x8b\xcf\x72\xb9\x74\x04\x16\x02\x53\x70\x16\x17\xd6\xba\xa9\xce\xa5\xb9\xae\x4e\x25\xbd\x00\xee\xcc\x00\x0e\xc8\x80\xb3\xab\xbb\xbb\xeb\xcd\x8d\x81\x0d\x10\x54\xfa\x3b\xbc\x6f\x6f\x6f\x6d\x8d\x2b\xcc\x94\x92\x1f\x48\x59\x33\x2e\x81\x28\x8e\x0b\x03\x45\xd4\xe1\xd3\x3a\x08\x76\x49\xb0\x19\xc7\xd2\x98\x72\xc2\x39\x56\x12\xb8\xdf\xf5\xdd\xdd\xc3\xd5\x6f\x27\x82\x28\x97\xe4\x19\xb7\xa7\xda\x8f\x7e\x9c\x5c\x57\xdc\x14\x3b\x61\x41\xff\xdc\x8c\xb4\x41\xc2\x75\x90\x31\xda\x36\x70\x5d\x37\xf1\xb5\x21\x3f\xd0\x1d\xcf\x93\x6f\x18\x6c\x0f\x71\xd0\x90\x0e\x61\x58\xde\xab\xcf\xd8\x0b\x20\x5e\xf9\x11\x72\x8c\xdb\xfc\xb8\x68\xdd\x30\x06\xce\x77\x38\x51\x8c\x9e\x61\x1e\x50\xf4\xa7\x32\x63\x78\x8a\x32\xc4\xa7\x74\xdc\xdf\x9f\x3a\x60\x22\xd2\xdd\xfb\xcb\x97\x2f\x5e\x40\xad\x51\x9b\x03\x16\x33\xe8\x61\xd9\x13\x91\x8a\xb6\xd2\xf1\xda\x96\x62\x67\xb1\x14\x7a\xc1\x15\xd4\x02\x8e\x86\x08\x58\xe9\xc9\xf6\x2a\xbb\xfe\x77\x23\x24\xd9\x1e\x22\x4b\xa3\x76\xbb\xd3\xe7\x9d\x99\x92\x75\x4c\x78\xfd\xd0\x6e\xe8\xc5\x08\x86\xa7\x52\x9c\xe8\xf7\x0e\x04\x04\x0d\xbb\x69\x80\x4d\xc2\x99\x0e\x1c\xf7\x58\x45\xaa\xaf\xce\xf6\x4b\xc3\xb3\xeb\xd5\x24\xcf\x8e\x08\x61\x13\x4e\xde\x61\x08\x54\x01\x1e\x85\xdb\xab\x47\xdb\x50\x8c\x3a\x2f\xf8\xd6\xeb\x71\x3e\x7f\x07\xe9\x7a\xb7\x32\xbd\xc6\xc6\xd3\x54\x4e\x37\xaf\x2a\xe2\x89\x53\x4b\x8d\x0e\x2f\xe9\x11\x23\xa4\xe7\xab\x9a\xe4\x3e\x8b\x26\x2b\x89\x7c\x9c\x4f\x0a\x28\x4c\x1e\x5b\xa7\xc4\xdf\xd5\xd5\xfe\xab\x2b\xbe\x4d\x64\x27\xdc\xfe\x8e\xed\x37\x88\xee\xbd\x93\x6f\x30\xdf\xd4\xd1\x7c\x8f\xf3\x27\x48\xf3\xc7\x30\xa9\x79\x33\xa2\xca\x2f\x70\x4d\x92\x1c\xd1\x2e\xc7\x4a\x52\x14\xf4\x24\x36\x2d\xf4\x48\x24\x13\x7d\x6a\xcc\x78\x0e\x4d\xba\xa1\x9e\x6d\x2c\xd2\x86\x0d\x2f\x4f\xa3\xe4\xf3\x4d\x1c\x8f\x0b\x86\xa2\x0c\xd3\xf0\x35\x3c\x4b\xb1\xf5\x61\xbd\x5e\x8f\xab\x23\x38\x90\x78\x55\x9a\xfa\xdd\x53\xb9\xfd\xff\x51\x9b\xdf\x0e\x3a\xe7\x6a\x4e\x9e\x91\xc4\x33\xaf\x70\xbb\xf7\x39\xd3\x95\x67\xee\x58\x3c\xda\xf1\x0f\x19\x91\x1e\xa4\xae\xb0\x94\x3c\xfc\x02\x2c\xe9\x6c\x0c\x88\xb9\xb6\x2d\x1b\x6f\x0f\x02\xdd\x0f\xa6\xe1\x31\xc6\xed\x38\x81\xbc\xd6\x4d\x65\xd0\xd9\x9e\xc4\xbf\x7f\x65\x8d\xd4\xbb\x69\xeb\xd2\xb2\xc2\x2b\x59\xa6\x2e\xbe\xea\x6b\x87\x2c\x3c\x76\x7f\xfa\x80\x72\x4c\x91\x2a\x0f\x4b\x37\xc6\x65\xd7\x48\x60\x20\x74\x26\x97\x8e\x16\xa3\x4b\x2f\x51\xd5\x14\xec\xe6\x74\x3f\x21\xee\xa1\x32\x70\x65\xf8\xb8\x5f\xb4\xaf\x37\xae\xd5\x19\x72\x87\xaa\xf1\x6b\x9b\x13\xa1\x4e\xba\xc3\x71\x2c\x08\x80\xaa\x40\x2b\x69\x8f\xe0\x47\x09\x6d\xb3\xf8\xcd\x81\x27\xf5\xc3\xea\x6b\x84\xa8\x7b\xac\xb0\x56\x02\x5d\x5e\x4d\x57\x4f\x70\xb2\x76\x72\x2b\xfd\x16\x11\xb8\xc1\x6b\xb2\x0a\xbd\xa1\x8c\x0a\xa1\xb3\xd6\xf7\x4d\xf3\x3d\x32\xbd\xc5\x09\x59\x5f\xf6\x9b\x77\xba\x5b\xaf\x82\x63\xd1\x50\x29\xbe\xe3\xd5\x20\x9e\x7c\x2f\xf0\xd9\xc6\x00\xd8\xfd\xc3\x05\x12\xf7\xbf\x61\x14\xf7\xf8\x2c\xc7\xf5\xea\xa8\xf6\x6a\x75\x58\xff\xb9\x20\xcf\xed\x89\x53\xbd\xd3\xd1\x41\xbb\xed\xce\xef\xdd\x59\x30\xb9\x65\x4e\x76\x0e\x1b\xaa\xd3\xc0\x8b\x60\xdf\xe5\xae\xae\x6e\x6f\x86\x5d\x49\x4a\x1c\x3c\x26\xb0\xca\x52\xbb\x65\x5b\xe5\x88\x34\x06\xe3\x10\x4e\x53\xf8\xd3\x98\xf5\xd1\xb0\x38\xb9\x9d\xdb\xc1\xcc\x53\x1a\x78\x21\x99\xcc\x97\xd1\x2c\xae\x93\xc5\x96\xc3\xd8\xaf\x37\x03\xe8\xcd\x1f\x56\x83\x0e\xcd\x64\x20\x46\x7d\x6b\x38\xe6\xbc\x42\x4e\x30\xef\x20\x39\xc1\xbb\xff\x00\x01\x9c\x3a\x2f\x7b\x14\x00\x00" - -func bundle_css_gz_bytes() ([]byte, error) { - return bindata_read( - _bundle_css_gz, - "bundle.css.gz", - ) -} - -func bundle_css_gz() (*asset, error) { - bytes, err := bundle_css_gz_bytes() - if err != nil { - return nil, err - } - - info := bindata_file_info{name: "bundle.css.gz", size: 1544, mode: os.FileMode(438), modTime: time.Unix(1432348676, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _bundle_js_gz = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x0b\xd4\xbd\xd9\x62\xdb\xc6\xb2\x28\xfa\x7e\xbe\x42\xe2\xce\x66\x80\x10\xa2\x48\xd9\xce\x00\x1a\xe4\x72\x6c\x39\x76\xe2\x29\x9e\x12\x87\xe6\xd2\x82\xc8\xa6\x04\x0b\x04\x68\x00\x94\x2c\x0b\xbc\xdf\x7e\xab\xaa\x67\x00\xa4\x64\x27\xfb\xec\x7b\x1f\x6c\x11\x40\x0f\xd5\xd5\xd5\x35\x75\x75\xf5\xee\x7c\x95\x4c\x8b\x28\x4d\x76\x0a\x87\x79\x89\x97\xb9\x57\xea\x4d\xe4\x84\x5e\xee\x5e\x45\x73\x67\x37\x19\x87\x13\xfe\x8b\xd1\xaf\xf3\x30\xdb\x59\x05\x2d\x59\xb4\x15\x04\xc5\xe5\x92\xa5\xf3\x9d\x8c\x7d\x5c\x45\x19\x6b\xb7\xc5\x8f\x01\xd6\xc9\xdb\xed\x95\x9b\xb1\x62\x95\x25\x3b\x2b\x68\x74\xb7\xe7\xe2\xfb\x54\xbe\x4b\xc5\x3b\x6c\x75\x1a\x24\xec\x62\xe7\x30\xcb\xd2\xcc\x69\xdd\x0f\x93\x24\x2d\x76\xe6\x51\x32\xdb\x59\xa4\xb3\x55\xcc\x76\xbe\x6d\x75\xc2\x4e\xeb\xdb\x96\x3b\x28\x4e\xb3\xf4\x62\x67\xda\x9d\xa6\x33\x16\xb4\x9e\x3e\x7f\xf0\xe6\xc9\xe1\xd1\xb3\xe7\xaf\x8f\x1e\x3e\x7f\xf3\xec\x41\xcb\x9b\xae\xb1\xbd\x38\x40\xd8\x83\x2b\xf6\x69\x99\x66\x45\xee\x5f\xad\xd7\x03\x1c\xc3\xb8\x37\xe9\x4e\xc3\x38\x76\xe2\xae\xf8\xe4\xc9\xd1\x38\x05\x1f\x60\x12\x50\xc1\xfe\x64\x5c\x4c\x06\x02\xd4\xc8\x49\x46\x89\x5f\xb8\x6b\x2f\xf6\x74\xcd\xc2\xe3\xb8\x5b\x8b\x52\xd8\xa5\xfc\xb8\x9e\xc3\x48\xb0\xb9\xf4\x26\xf8\xf2\xc2\xa0\x37\x08\xef\x66\xdd\x98\x25\x27\xc5\xe9\x20\xec\x74\xdc\xc8\xc9\x10\xe9\x0a\x84\xb5\x73\xd5\xf7\xc7\x1a\x5a\xec\xdc\xbd\x6a\xad\x72\xb6\x93\x17\x59\x34\x2d\x5a\x84\xc9\x2c\x28\x9c\x56\xc6\x42\x78\x76\xbd\x48\x3d\xec\x65\xe9\xaa\x60\x19\xbc\x4b\x83\xa8\xfb\x12\x1f\xa0\xd3\xa8\xfb\x80\xcd\xc3\x55\x5c\xd0\x8b\x01\x14\xee\xee\x47\xd9\x14\x4a\xd1\xcf\x69\xba\x58\x84\xc9\xac\xc5\xe7\x28\x0f\xe8\x65\x9e\x4e\xcf\x18\x36\xbe\xe2\xcf\xab\x22\x8a\xe1\x69\x1a\xc8\x2a\xcb\x34\x61\x49\x91\xef\xdf\x5b\x2e\xbb\x1f\xf2\x4f\xf0\x2d\xae\x7d\xbb\x9f\x26\x09\x9b\x16\xe2\xfb\xb2\xfe\xfd\x34\x94\x1f\xe7\xb5\x8f\xaf\x58\x51\x44\xc9\x49\x2e\x0a\x9c\xf2\x02\x21\xe1\x25\xdf\xa7\x81\xc2\xeb\x59\x10\xa7\x30\xd5\xaf\x8a\x34\x0b\x4f\x58\x77\xb5\x8a\x66\x83\x59\x59\x3a\xa7\xdd\x24\x3c\x8f\x4e\xc2\x82\x39\xad\x29\x07\xa3\x85\x74\xe8\xd5\x8a\x07\xb3\x60\xd5\x7d\xf3\xe6\xf1\x03\xc7\x75\xbd\xbc\x0b\x48\xd7\x15\xd4\x3c\xb8\x57\x62\x82\xf2\x6e\xce\x92\x99\xd3\xc2\x9a\x2d\x6f\xe6\xae\x65\x1d\x86\x54\xdd\xb2\xe8\x4c\x54\x81\xd6\xf2\x34\x66\xdd\x38\x3d\x71\x0a\xa8\x9e\x9d\xb3\xac\xd3\xf2\x77\x5a\x9d\xa2\xbb\x60\x79\x0e\x80\x40\x33\x84\xfc\xf3\x20\xeb\x4e\x61\x26\x0b\x76\x18\xb3\x05\xa0\xc1\x49\xbd\xab\x24\x5c\x30\xbf\x15\x2e\x97\x2d\x6f\x19\x16\xa7\x7e\x6b\xbf\xe5\x9d\xc2\x84\xc5\x2c\xf3\xa7\x6b\x6f\x63\x0d\x35\x0a\x59\x38\x06\x60\x37\x96\xce\x05\xba\x75\xf1\xf9\xd6\xe2\x45\x58\xac\x72\x05\x91\xcf\x87\xa5\x2b\x2f\xb7\x55\x9e\xc2\xbc\x57\xab\xee\xfb\xf0\x16\x00\x8e\xb7\xb7\x11\x7a\x57\x06\x7c\xc0\x6a\xba\xd9\x2a\x71\xce\xbd\xa8\xfb\x28\xca\x61\x56\x2f\x9f\xc0\xfc\xe2\x04\xd8\x33\xd1\xcd\x60\xd6\x58\xe6\x54\x9b\x2b\xbc\x64\x15\xc7\x40\x46\xe9\x74\x85\x2f\xba\xc7\xe9\xec\x12\x66\x63\xed\x5d\xd5\x88\xcd\x3f\xb8\x75\xdb\x33\xd6\x0b\x3c\xff\xe8\x35\x2f\x06\xf8\xf4\x93\xb7\x81\xd6\xfd\x83\xdb\xbd\xea\x37\x63\x9d\xc0\xe7\x03\x6f\xcb\x4a\x80\xef\xd4\x2b\x2e\x60\xff\xe0\xce\x2d\x4f\x2f\x56\x78\xbc\xe3\xc9\xb5\xea\x1f\x7c\x7f\xdb\x23\xa6\xe0\x1f\xf4\x00\x18\x8b\x3f\xf8\xb7\x7b\xeb\x89\x77\x50\x67\x34\xbb\xc6\x0b\x10\x17\x0d\x4c\x6d\xc6\x80\x63\x03\x4f\xe3\x7f\xbb\xe1\x62\x36\xe2\x3f\x9d\xf1\xa4\x61\xbd\x14\xdd\x7b\xab\x22\x8d\xa3\xe4\x8c\x65\x41\xe6\x00\x6a\xfd\x56\x7a\xfc\x01\xe9\x52\x35\x99\x8c\x98\x64\xa8\x58\xc4\xaf\xd5\x71\x8a\xd3\x28\x37\x1b\xc7\xb5\x52\x04\xea\x05\x73\xaf\x8a\xee\x1b\x18\x75\x37\xcc\xf3\xe8\x24\xe1\xe5\x19\x5f\x53\x49\x80\x4f\xdd\xd3\x30\x3f\x2d\xc2\x13\x94\x4d\xc9\x6e\x10\xec\xf6\xdb\xed\x56\x71\x11\x15\x88\x0e\x78\x4e\xe0\x71\x1e\x4e\xd9\x71\x9a\x9e\xd1\xb3\xcb\x45\x90\x21\xb0\xa2\xe4\x3c\x8c\xa3\xd9\xce\x7f\x44\x53\xff\xd9\x99\xce\x4f\x76\xf6\x76\x72\xc6\x76\x80\x7e\xf2\x96\xbb\x1e\xa8\x51\x2f\xb3\xb4\x48\x71\x7c\xc1\x15\xae\xff\x22\x5b\x4d\x81\x3a\xfd\xc2\x5b\x65\x71\xee\xef\xf6\x3c\xb6\x08\xa3\x18\x7f\x08\x20\xf0\xe7\xf2\x14\x66\x1c\x7f\x88\x1e\xfc\xdd\xbe\x07\x00\xfc\x01\x22\x32\xbd\xc0\xf7\x28\x02\x96\x2f\x32\xc0\xf7\x27\xaa\x0a\xb4\x0f\xd4\xce\xfc\xf3\x14\xe0\xea\x79\x67\x8c\x2d\x9f\x67\xd1\x49\x94\x84\xf1\x6b\xf6\xa9\xc0\xfa\xd3\x18\x70\xf2\x8c\x96\x1d\xac\xac\x62\x11\xbf\x08\x33\x58\x71\xb2\xca\x22\x2c\xa6\xa7\xf6\x2b\xe8\xf8\xe7\x55\x14\xcf\xf4\x1b\x9c\x0a\xdf\x5c\x4f\x52\xec\x31\x8e\xdb\x13\x56\x3c\x52\x2d\x3b\xae\x07\xc2\xb5\xbb\xc4\x07\x28\xeb\x65\x41\x0f\x24\x14\x10\x47\x0a\x3f\xc2\x20\x51\xd2\x6f\x98\x0e\x52\x90\x80\x57\x5c\xea\x24\xe3\x74\x02\xc2\x86\x1a\x7b\x0d\x78\x73\x50\xd8\xf0\x27\x18\x89\x43\x4a\x45\x8b\xf1\x65\x0b\xa4\x13\xac\xdc\x56\x88\x7f\x79\x91\xf0\x04\x87\xe8\xb8\xed\xb6\x93\x77\xa3\xfc\x7e\x9c\xe6\xb0\x62\x1c\x77\x94\x05\x4f\x81\xcd\x74\x17\xe1\x27\x27\xdb\xeb\x7b\x3d\xd7\xcf\xa0\x4f\x60\x17\xcb\x55\x7e\xea\x4c\xdd\x01\x8b\x41\xb4\x52\xdb\x49\x11\x15\x97\xd4\x74\x59\xb6\x70\x91\xab\x9e\xea\xa5\x7b\xf0\x3e\xe3\xa0\xc7\x1c\x07\x88\xa3\x68\x7e\xf9\xaa\xc8\xb0\x9c\xa8\x11\xbb\x6b\x5e\x43\x36\x20\x95\x88\xa8\xfb\x21\x8d\x40\x6a\xb4\x50\xd9\x50\x35\xfd\x06\xe9\x21\x11\xfc\x54\x4f\x94\xe3\x02\x3b\x5b\xc6\x40\xad\xb0\x4a\xe9\x3b\x67\x6a\x54\xe4\x25\x55\x7b\x1b\xc6\xf4\x05\x9a\x6f\xfa\xe6\x9b\x4b\x87\x16\x09\xa2\x97\x9a\x12\x2d\x3f\x84\x05\xe1\x88\xa5\xa3\x5e\x71\xa5\x8a\x16\x97\x58\x61\xae\xd7\x42\x9a\x4c\x4e\x8c\xd5\x2c\x35\x3f\x6a\x33\x09\x70\xad\xc9\x57\x4c\x8d\x84\xcd\xf4\xb4\x02\x3a\x60\x85\x84\xc9\x14\xab\x17\x5d\x24\x25\x98\x50\xd5\x4c\xb7\x48\xef\x25\xd3\xd3\x34\x7b\x45\x3d\x39\xae\xd4\x80\x04\x66\x5e\x2b\x7a\x75\x50\x17\xca\xba\xc7\xf8\x04\x23\x53\x4a\x55\xad\x85\xb5\x67\x91\xac\x5f\x61\x2d\x82\xac\xf5\x6a\x91\x2d\x31\xd0\x2c\x6a\x1f\x49\xa9\x2d\x8c\x17\x5d\xdd\xb2\xeb\x31\xea\xcb\x98\xbd\x0d\x9d\x19\x0b\xb1\xa1\x37\xe3\xab\xe8\xce\x78\xd3\x35\x69\xe3\x8a\x18\x0c\x55\xc2\x5f\x82\xcf\xd0\x33\xfd\x54\xfc\x86\x5e\x89\x07\xc1\x79\xe8\x15\xfd\x54\x1c\xc8\xe4\x9d\x16\xfb\xa1\x0f\xc6\x8b\x3a\xf3\xa1\x12\xd5\xb7\x20\xb3\x05\x4a\xf4\xb4\x6d\xc0\x88\xe6\x43\x0d\x08\xd1\x1f\x05\x3e\xf8\x04\x1b\xb4\x70\xa5\x39\x27\xd5\x50\x8f\x9a\x6d\xf2\x96\xc4\x93\xc1\x29\xf9\x9a\x92\x8f\x1c\xe4\xb5\x57\xd0\x1a\x37\xa4\x0e\x0a\x4c\x4e\x8a\x04\x82\x93\x28\x8a\xcb\xa8\x28\x90\x20\xd6\xa2\x99\x0a\xae\xf0\xa7\x41\x34\x57\xea\x93\xf9\x02\x85\x58\x70\x15\x1e\x03\x62\x41\x5c\x3f\x65\xc5\x69\x3a\x33\xd1\x43\x42\xa9\x25\xbf\xb7\xa0\x4a\x16\x2d\x5e\xb2\x13\xf6\xc9\xdf\xff\xf7\xf8\x7d\xfe\x7e\xf5\xf0\xf0\xe1\xc3\xf7\x9f\xee\xf5\x26\x9d\xb2\xf2\xfc\xcd\xfe\x89\xc7\xe5\xa3\x6f\x8a\x7d\xcd\xcd\x71\x1d\xee\x30\x97\xe1\x7c\x3f\xbf\x48\x5e\x64\xe9\x92\x65\xc5\x25\x8c\x0b\x78\x41\x31\x4e\x26\x60\x33\x25\xda\x56\x29\xd6\x1e\x4c\x28\xe8\x55\x7e\x13\x4a\x98\x16\x81\xb0\x28\x8d\x21\xac\x91\x39\x2a\xe9\x98\xd1\x62\x06\x49\x00\x82\xa1\xd2\x6d\xcb\x10\x9c\x2d\x77\x04\xdc\xc7\x10\xa4\xa6\xa6\x61\x7e\xe8\x82\x9e\x1c\x5f\x72\x1e\x15\x66\x27\xa4\xd4\x01\x17\xa4\x5e\xc2\x20\x35\x7a\xc6\x39\x8b\xe4\x58\x42\xb3\x8d\x20\xf5\xc2\x6e\xbe\x02\x28\x88\x06\x82\xcc\x9b\x81\xe0\x29\xd8\x8e\x05\x82\x67\xab\x1c\x21\x0c\xdd\x4b\x01\x25\x71\x1c\x2d\xf3\x28\xf7\xab\xaa\x95\x52\x0d\xb8\xfc\x1b\x32\x62\xb0\xa8\x7e\x82\xb6\x31\x6a\x75\xbb\x2d\x3f\xf1\x8a\x00\x2c\x84\xd5\x31\xe7\xa9\x0e\x68\x09\x7b\x52\x5e\xba\x1d\x68\x1f\x50\x0e\x24\xcc\x3e\x3d\x9f\x57\xa6\x10\xb8\xe8\xbd\x2c\x0b\x2f\xf5\xf8\xba\xa2\xa0\xab\xfa\x15\x2f\x90\x31\xaa\x19\x07\x91\x0c\x8c\x54\x8a\xe4\x6c\x98\x0c\x12\x34\x4a\xe7\x7c\xba\x83\x80\x69\x66\xce\x7f\xec\xf5\xd7\x5e\xbe\x8c\xa3\xe2\x5e\x32\xbb\x1f\x2e\xe1\x15\xab\x83\xb2\x0b\x7c\x3e\x4e\x8f\xc3\xb8\xae\x44\xfd\x87\x2a\x13\xc5\xfe\x67\x67\xb1\xca\x8b\x9d\xd3\xf0\x9c\x81\x94\x03\xeb\xff\xe4\xdb\x9d\x79\x1c\x9e\x80\x42\x05\x86\xa7\x86\x11\x20\x04\xed\x21\x02\xdb\x19\xf5\x0a\xf6\x89\x4d\x41\x3c\x0e\xdc\x8c\xcb\x54\x13\x5f\x91\x97\xf0\x51\xba\x68\x38\xd0\xe7\x64\xdc\x9b\xa0\x54\x10\x1f\x3a\xf8\xac\x86\x2b\x17\x6b\xbd\x21\x6c\x80\x2f\xae\x46\x99\xac\xe5\x2f\xe7\x20\x62\x0d\x7a\x28\xcf\x71\x19\x0b\x11\x16\x08\x12\xe1\xcb\xc4\x79\x4e\x7a\xaf\x77\x75\x71\x1a\x15\x2c\x5f\x42\x7d\xb1\x72\xdf\xe7\x9d\x7d\xaf\x91\xba\x37\x69\xb6\x5c\xec\x47\x60\x36\x64\xd8\x57\x60\x3f\x96\xa5\xf1\xfc\xfa\xe9\x13\x98\x32\xa5\x23\x6d\xd4\x31\x0a\xfe\x3d\xe0\x2a\x85\x64\xd1\x76\x95\xc6\x1a\xa0\x2d\xb5\xa8\x87\x7b\x85\xa5\xc2\x78\x52\xb7\x50\x92\x1a\x0b\xe4\x8e\x62\x20\xc9\xb8\x00\x96\xa2\xbb\xab\xd4\xaf\xa9\x40\xa2\x3a\xd4\x52\xdd\xe5\x75\x4d\x66\x53\x6f\x36\x1e\x13\x89\x44\xd5\x73\xbe\x69\x98\x21\x7e\x04\xc9\xa3\x1f\x80\x57\xbb\x04\xc2\x7d\xe4\x0f\x1b\x41\x16\x30\x02\x23\xc3\x62\x2d\x0f\x3d\x4b\xe1\x6c\x56\xa9\x64\x32\x60\x4f\x6b\x35\x54\x8a\x14\x1a\x7a\x53\xa1\x19\x50\xa6\xc5\x78\xc4\xaa\x06\xcd\x3a\x1b\x65\x5d\x5a\x5d\x40\xbe\x3e\xac\x98\x1c\x56\x8b\x7c\x86\xa5\x03\xf0\x9c\x46\x73\x54\xb9\xdc\xbd\x3e\x2c\xed\x94\x58\x56\xbb\x1d\x8a\x85\xa2\x11\x55\x41\xb7\x00\x7f\x12\x84\x42\x69\xdd\x69\x49\xd4\x65\x6c\x91\x9e\xb3\xff\x95\x01\x85\x62\x15\x13\x17\x55\x63\x83\xc1\x09\xff\x25\x1f\xde\x60\xaf\x0f\xc6\xdc\x0a\x47\x89\x35\x61\xc5\xae\xbc\xbe\xd2\xc2\xbf\x60\xa4\x27\xb5\xc9\xde\x48\x9e\xb2\x15\xbe\x2e\x40\xa8\x6d\xa2\x12\x82\x0d\x3b\xe9\x54\x70\xd4\xc1\x8e\x15\xbf\xa6\x02\xf4\x8a\x68\xee\xb1\x5c\xe5\x1b\xe9\xce\x60\x0b\x1a\xfa\x86\x6a\x1b\x6a\x71\xb8\x6d\x95\xb9\xaa\xa2\x15\xa6\xf6\xcd\x4d\x2f\x4f\x68\x66\xa4\x7d\x13\x2e\xd0\x16\x52\x54\xc5\x02\x36\xc2\x91\x90\x1d\x3a\x6e\xdd\x6d\x91\x63\xb5\x35\x6c\x79\xb2\x25\x05\x21\xb4\xd5\xba\xbb\x8f\x05\xe0\xf3\xc4\xb0\x94\xac\xa6\x4d\x90\x50\xe6\xe8\xe5\x29\x64\x56\x8b\xbb\x4a\x8b\x2a\x43\x00\x40\xc7\x93\x81\xa5\xf4\x14\x6e\xd1\xa4\xf4\x30\xb1\x34\x3a\xdf\x06\xad\x6f\x3b\x28\x12\x3b\xdf\xb6\xbe\xd5\x43\xd2\x54\xb2\x5e\x03\xa1\xd4\x74\xd0\x0d\xfc\xff\x8b\x38\xbd\x18\x75\x03\x9f\xe3\x7a\xaf\x10\x35\xce\x95\xe0\xc6\x3e\x98\xc5\x1e\xa1\xc1\x37\x4c\x43\x3e\x74\x66\x18\xd7\xf4\x9b\x03\xfc\x08\x14\x78\x74\x7e\x2a\x0a\x10\x86\x40\x96\x4e\x59\x9e\x8b\x41\xa1\xb5\x66\xd4\xe1\xd6\x1b\xfa\x2d\x25\x33\x97\x96\x66\x85\x97\x1a\x62\xe0\xea\x14\x3a\xf2\x41\xfb\x17\x4c\x81\x97\xbf\x9f\xf3\x05\x82\x42\x5d\x4a\x64\x5c\xd4\x7a\x35\x66\x42\xdc\x29\x0d\x1e\x3f\x83\xf4\xc9\x00\x9a\xa0\x75\x74\x1c\x87\xc9\x19\x2c\x54\x05\x81\x6c\xd1\x5a\x20\x86\x61\xa1\x34\x7b\x35\x91\x23\xd6\x21\xda\xec\xb4\xf6\x60\xad\xf9\x48\xff\xb5\xd1\x37\x2e\x37\xde\xe0\x2c\x7d\x2d\x8c\x08\x07\x79\xbc\x7e\xb4\x66\xcd\x96\x43\x52\x4f\x74\xb8\x00\x54\x66\x48\x59\x3e\x5b\x2d\x8e\xc1\xa8\x7b\xf1\xfc\xd5\xe3\xd7\x8f\xdf\x1e\x1e\x3d\x7e\xf6\xf0\xf1\xb3\xc7\xaf\xdf\x09\x22\x6b\xb4\x33\x37\x50\x1a\x96\xe5\x3a\x46\x6d\xfd\xee\xef\xee\xed\x39\x68\x21\xbc\x9a\x74\x46\xee\xde\xde\x3e\x2c\x8b\xfd\x71\x6f\xef\xa7\x70\xef\xf3\xbd\xbd\xbf\x26\xfa\xa7\x3f\xf9\x6e\xdf\x4b\xe0\xe3\xbf\xa1\x74\xaf\xf5\xed\xf0\xfd\x7e\xf0\xfe\x53\xaf\xbf\xf7\xfe\x53\x1f\x4c\x8b\x1f\x1e\x4e\x40\x7b\xc9\x82\x7d\x67\xe4\xb7\xc6\xff\x6e\x4d\xbe\x1b\xb5\xca\x6f\xc7\xff\xfe\x16\x7e\x7c\x5b\xc2\xdf\x56\x70\x77\xf8\x9f\xf7\xf9\xa4\xe3\xee\x93\x22\x96\xa7\xab\x6c\x0a\xa8\x86\xf2\xef\xdf\xe7\xdf\x05\xf8\x5f\xab\x93\xa9\xf7\xee\xa8\xa5\x88\x0a\x48\x1c\xe0\x3f\xfc\xb4\x74\xc6\x58\xbe\x05\x8c\xc1\xd9\x7d\xf0\xfc\xfe\xeb\x77\x2f\x0e\x5d\x78\xe2\xef\xa0\x85\x8e\x7c\x88\xbc\x56\xd9\xf2\x8c\xd6\xe0\x83\xfb\x5d\x8b\x38\x0d\x3d\x94\xaa\xda\x5d\x67\x1f\xfa\x12\x4f\x85\xa8\x61\x16\x70\x80\x24\xac\x86\xcc\xee\x22\xd1\x2e\x82\xbf\x3f\x12\x8d\xbb\xaa\x23\xcd\xb7\xbc\xd6\x49\x04\x1c\x02\xd6\x1c\x4e\xc7\xfd\xd3\x10\x4d\x37\x96\x1d\xa2\xbf\x29\x62\xb9\xd0\x01\x9d\x76\x72\x9c\x2f\x07\x65\xfb\xbf\xfa\xdf\xf7\xe0\x4f\x5c\xe0\x6f\xfa\x79\xc2\x7f\x1e\xc0\xff\x1f\x57\x29\x3d\xdc\xba\x4d\xff\xff\x34\x70\xf7\x4f\x22\x8f\x7c\x6d\xcd\x0e\x3a\x4f\x89\x60\x45\x0b\xa8\x4a\x83\xb8\x05\x1e\x88\xc6\x07\x8a\x20\x30\xc3\xa4\x5e\x2d\x05\x68\x08\xb6\x5e\x8f\x44\xee\xf8\x16\xfa\xe5\xd8\xb8\x0f\x02\x8d\x8d\x6f\x4f\xbc\x69\xb0\xbb\xcb\xc6\x07\x13\xdc\xf0\xb1\x94\x6f\x61\x73\xb8\x83\x58\xfb\x8e\x08\x34\x5c\x3e\x60\x2f\xd0\x88\x2f\x9f\xa5\x33\x96\x3b\x31\x18\x4b\xc4\x5d\x85\xc1\x96\x82\xb0\x96\xaf\x9c\x7c\x64\xf2\x07\xee\x89\xc3\x6a\xb4\x67\x69\xb2\x35\xe1\xc6\x17\xdf\x56\xde\x14\xb9\x58\x20\xe0\xe8\x48\x15\x61\x0d\xe2\x21\xba\x2b\xad\x1c\x3e\xbe\xa5\x0d\xbb\x3b\x58\x5e\x0f\xf3\xb2\x09\x66\xa9\x4b\x80\xe9\xb7\xa1\x5e\xb3\x66\x84\x36\x8d\x5a\xb6\x15\x8b\x4a\xf2\x84\xcd\xf4\xe2\x8a\x49\x54\x7b\x89\xe9\x30\x1a\x44\x9d\xe0\x40\xce\x5e\x36\x8e\x70\xf6\xe0\x4f\xa7\x3f\x19\x84\xed\x76\x22\xac\x1c\x8d\x3c\x84\x94\x63\x0e\x37\xbe\x9a\x4a\xe8\x41\x38\xb9\x1e\xa9\xe6\xb3\x7a\x66\x2a\x2e\x00\x63\xf9\x5a\x0c\xcb\x9c\xcb\xab\x02\x99\x2a\xf3\x84\xa7\xd5\x17\xa8\x40\x63\x0a\x84\xef\x5a\x79\x2e\x8d\x39\xb6\x7a\xc1\xfd\x89\x4d\xfd\x98\x74\x21\xfb\x91\xf2\x11\xfd\x89\x4f\xd2\x0b\x96\xdd\x0f\x73\xf2\x32\x73\x5f\xb1\x9f\x19\x5d\xaa\x71\x37\x31\xf0\x7a\x6f\x1a\x4d\xa2\x33\xdd\x94\x44\xf2\x8d\x1a\x52\x33\xa2\x9b\x69\x62\xf9\x58\x64\x03\xc3\xa7\x7a\xa0\x60\x7d\xa1\x8a\x21\xd4\x02\x39\x07\xb6\xff\xc9\x13\x3e\xf8\x8d\x66\x20\xba\xf5\xaa\x70\x1a\x33\x5d\x01\xb5\x71\x38\xa8\x14\x71\x32\x00\xe0\x25\x34\xb5\xfe\x94\x57\x9e\xeb\xe3\xa2\xc6\x06\xb0\x44\xd9\x1a\x64\x06\x6d\xdc\x0c\x32\xa5\x58\xb5\x14\xad\xec\xf6\xb7\x00\x29\x37\x29\xbe\xc0\x84\x5e\x7b\x6a\xcf\x62\xe3\x70\xf8\xe7\xfa\x70\x14\xf1\xdd\x6c\x34\x5b\xe0\xe6\x1b\x20\xb5\x1e\x24\x55\xfe\xdd\xf6\x91\x4e\x44\xeb\x1b\x9c\xd7\x1b\x88\xfa\x4b\xb7\xcc\x2a\xbb\x64\xd4\x19\xcb\x36\xe9\x41\xce\xbf\x41\x49\x79\x7f\x31\x71\xff\xe5\xbc\xbf\xb8\xea\x7b\xfd\x3b\x6b\x97\x94\x21\xf5\xe1\xbf\xcc\x0f\x09\x29\x3a\xe3\xf7\x7b\x03\xbf\x1d\xbc\xef\xbc\xff\xc6\x7b\x7f\xf1\xbe\x3b\xe9\xfc\xcb\x95\x4a\xd0\xfb\xce\xe8\xfd\x0c\xca\xdf\x5a\x8f\xf7\xde\xe7\xdd\x89\x3b\x7a\xef\xe0\x9b\x5b\xeb\xf7\xee\x88\xbf\xe2\x8f\xfc\x37\xfc\xbc\xbd\x46\xcd\x88\xda\x05\x7d\x0b\xb4\xae\xc9\x78\xaf\xdb\xe1\x3f\x41\x0d\x9b\x74\x7c\x67\xb4\xbb\xe9\xd3\xfb\xfd\xf7\xfb\x2e\x7c\x7f\x3f\xeb\xbc\xdf\x1f\xb9\x08\x00\xbe\x19\x01\x3c\x29\xb5\x79\x71\x01\x00\xc2\x53\x08\x2a\x9c\xaa\xf8\xbe\xfb\x7e\x6f\xf2\x9d\xf1\xbc\x37\xd9\x07\x79\xb1\xff\xbe\x0b\x35\xa2\x04\xb0\x9b\xd0\x36\x7a\x18\x97\x8a\x97\xc0\x23\x3e\x10\x6b\x48\xb3\xbc\x64\x58\x6c\x99\x45\x39\xcb\x4b\x98\x87\x22\x3d\xc9\xc2\xe5\xe9\x65\x09\xaa\xf3\x8c\x17\xcf\xcb\x79\xba\x4a\x66\xd4\x52\x19\x2d\x16\xe9\x71\x14\x47\x0c\x7e\x26\xb3\x15\xce\x12\x54\x5c\x84\x49\x78\x42\x0b\x06\xeb\xa1\xed\x85\x6f\x0b\x36\x3d\x4d\xd2\x38\x3d\xb9\x2c\xa7\xa7\xd0\x43\xb1\x08\xf3\x12\x57\xf4\x2a\x01\x1a\x2d\x67\x51\xc6\x10\x86\xcb\x92\x41\x4f\xbc\x79\x8c\xb1\x59\x52\x3b\xb8\x9b\x14\x15\x2b\xd0\xa5\x17\x61\x76\xc6\x70\xef\xbc\xcc\xd3\x78\xc5\x21\x3a\x0f\x79\x85\xbc\x3c\x06\x0b\x22\x8c\xf0\x47\x0a\xdf\x3e\xae\x58\x79\xcc\xed\x36\xe8\x0a\x58\x37\x6a\x06\xe5\x34\x66\x61\xc2\x7f\xa4\xb0\x0e\xf1\x47\xba\x58\xe2\x26\x7a\x39\x63\x8b\x74\x9a\x85\x05\x40\x13\x2e\xd2\x64\x96\x97\x34\xfe\x68\x9a\x97\xa7\x69\x3c\xc3\x1d\xfb\x32\x8e\x4e\x4e\xa9\x7f\xd0\x0d\x8a\x04\x5b\x5e\xc6\xa0\xde\x13\x44\x2b\x50\x22\x68\xac\x19\x00\x81\x6f\xce\x01\x78\x90\xfe\x79\x09\x10\x42\xe3\x30\xf4\x30\x63\x04\x0d\x74\x19\x26\xf0\x9c\xad\x08\xd9\xb3\x74\x41\x70\xe3\xa6\x79\xce\x66\xe5\x9c\xba\x01\x64\xc7\x29\xe2\xaa\x3c\x09\xe3\x98\x01\x72\x4e\x56\x11\x58\x49\x04\x4e\x34\x0b\x2f\xcb\xb3\x08\x57\x42\x52\x26\x0c\xb0\x1f\x66\x65\x7a\x16\x25\xe1\x45\x58\x02\x32\xa3\x25\xb4\x9b\x01\x00\x61\x8c\x7f\xcf\x23\x76\x91\x97\xf9\x69\x74\x96\x9f\x86\x25\x32\x9e\x18\xbe\x23\xc8\x69\x56\x94\xf9\x65\x5e\xb0\x05\xc0\x79\xc2\x92\xe9\x65\x09\xd6\x4a\x1c\x01\x69\x00\x23\xcb\xc2\x72\x4a\x64\x01\x30\xcf\xe7\x8c\x21\xbd\xcc\x52\x80\x38\x24\x2c\x30\x0c\x1b\x61\x25\xc3\x91\x12\xf8\x30\xdd\xe5\x7c\x55\x1c\xa7\x71\x79\x16\xae\xe6\x00\x5b\xbc\xfa\xb4\x02\xd0\x61\x80\x39\x4c\x2a\xe0\x15\xd6\x75\xb9\x58\xe5\x6c\xb5\x28\x81\x52\xd2\xcb\x90\xd3\x1a\x42\xb9\x0c\xa3\x0c\xff\x10\x4c\xe9\x34\x02\x62\x25\xac\x5e\x96\xd0\x4d\x91\xa6\x25\xd0\x12\x50\x1f\x62\xf8\x9c\xc5\xe5\x79\x14\x7e\x80\x51\x9c\x47\x31\x18\x80\xf0\x27\x47\xb2\x39\x4f\x09\xb2\x73\x68\xf8\x84\x95\x44\xd9\x9c\x0c\x10\xfb\x30\xa7\x80\xb0\x70\x59\x62\x1c\x1a\x8e\x22\x99\x02\xf4\xc8\x86\xca\x13\x34\x22\x01\xb3\x00\x19\xd2\xf0\x49\x5a\xc2\x1c\x7e\x08\x69\xa2\xc5\x72\x00\xfc\xa5\x88\xb5\x34\x06\x5c\x17\x29\xce\x40\x91\x9e\x5d\x02\x58\x69\x0a\x58\xbe\x40\xbe\x54\x5e\xa4\xd9\x19\x60\x92\x65\x69\x19\x66\xcb\xb0\x0c\xf3\x28\x04\x8c\xc2\x2c\x1e\x47\x67\x40\x91\x31\x91\xe5\xe7\xcf\x88\x5e\x80\x23\x5e\x1d\x03\x30\x29\xae\xca\x74\x59\xce\xc3\x6c\x51\xce\x23\xc0\xd0\x49\x34\x87\x79\x5f\x65\x2b\xa0\xfe\x79\x5a\x7e\x48\x8f\x73\x98\xee\x8b\xa8\x3c\xcb\x80\x40\xc0\x42\x86\xff\xa2\x45\x5a\xe2\xbe\x54\x09\xab\x64\x55\xe2\x62\x84\xff\x00\x3d\x18\x94\x53\x2e\x91\x6e\x97\xf8\x15\x68\xaa\x28\x3f\x2e\x01\x37\x59\x04\x00\x66\xab\xd3\xac\xcc\xd9\x27\x00\x1e\x0c\x56\xc4\x17\xc3\xff\x52\x80\x1f\xf0\x76\x81\xcb\xf9\x22\x3a\x8b\xca\xcf\xc0\x88\x71\x49\x01\xdc\x33\xf8\x87\x00\x1f\xe3\x3a\x02\x82\x48\x91\x82\x71\xa9\x96\x27\xe9\x39\x00\x58\x00\x68\x8b\x72\x01\x58\x4c\x58\x51\xa6\x49\x5c\xa6\xd9\x09\x2e\xff\x72\x09\xc3\x43\x80\x0b\x98\xae\x55\x02\x7d\xc0\xef\x4f\x9f\x3e\x95\x9f\x2e\x3f\xc3\xdc\x94\xe1\x0c\x30\x55\x86\x73\xa0\xbc\x32\x8c\x4a\x98\xef\x70\x51\x86\x49\x19\x02\xf2\x3e\x02\xfe\x00\x7b\x25\xf4\x18\xae\xca\xf0\xa2\x0c\x3f\x95\xe1\x67\x80\xa8\x3c\x3e\x2e\x8f\x01\x24\x80\x6e\x5e\x1e\x9f\x94\xc7\xa7\x00\x5e\x79\xfc\xa1\x3c\x5e\x94\xc7\x09\x2c\xfe\xf2\x18\x80\x06\x2e\x00\x28\x3f\x2f\x8f\x2f\xca\x63\x20\x69\x04\xbf\x9c\x4e\xcb\x29\xd0\xc1\xbc\x9c\xc2\xb2\x3f\x2d\xa7\x51\x39\x3d\x83\x29\x28\xa7\x8b\x72\x8a\xac\x10\x16\x64\x39\x5d\x95\xd3\xf3\x72\x7a\x51\x4e\x3f\x95\xb0\x16\xa6\x9f\x81\x2f\x94\xb3\x0f\xe5\xec\xac\x9c\x2d\x60\xa5\x96\xb3\xcf\x25\x9b\x96\xb0\x14\x18\xd0\x7f\x06\x4b\xa0\x84\x31\xb3\x15\x4c\x5b\x39\xff\x50\xce\xcf\xca\x39\x4c\x61\x5a\xce\x33\x58\xb6\xe5\xc9\x71\x79\x32\x2b\x81\x10\x4f\xe6\xe5\xc9\x49\x79\x82\x13\x0b\xa4\x56\x9e\x2c\xca\x93\xa4\x3c\x59\x96\x27\x1f\x81\xcb\x94\xc0\x59\x4e\x70\xba\xcb\x93\x8b\x12\x58\xe4\xe9\x59\x79\xba\x28\x4f\x93\x12\x66\xea\xb4\x28\x4f\x81\x08\x66\x65\xc4\x4a\x40\x30\xe0\x19\x96\x66\x94\x96\xd1\xc7\x12\x16\x4b\x94\x97\x51\x51\x7e\x60\xe5\x87\x05\xd0\x48\xf9\x61\x59\x02\x8d\x9d\x9d\x94\x67\xa7\x30\x25\xe5\xd9\xa2\x3c\x4b\xca\x33\x78\x99\x95\x67\x17\xe5\x19\x70\x8c\xcf\x40\x3b\x65\x7c\x5c\xc6\x53\x20\x9d\x32\x3e\x2b\xe3\xac\x04\xda\x8d\x0b\x58\xa8\x65\x7c\x5e\xc6\xb8\x54\xcb\xc5\xb4\x5c\xcc\x80\xac\xca\xc5\x49\xb9\x80\xe5\x0a\x24\x16\x97\x0b\x98\x62\x5c\xc1\x25\xd0\xed\xe2\x63\xb9\xc8\x4a\x60\x19\x8b\x02\x16\x73\xb9\x38\x2f\x17\x17\xe5\xe2\x53\x09\x4c\x6e\xf1\x19\x08\xb0\x4c\xa6\x40\x0b\x65\x32\x2f\x81\xa6\x92\xa8\x04\x92\x80\xd9\x4f\x96\x65\x92\x95\x40\xab\xc9\xe7\x12\x08\x08\x56\xc7\x12\x08\x75\x5e\x2e\x81\x58\x4e\xcb\x25\x90\x6a\x5c\x2e\xe1\x7d\x02\xb4\x53\x02\x6d\x2e\x41\x86\x5c\x94\xcb\xcb\xf2\x23\xf2\xb4\x12\xe8\x09\x98\x1f\x2c\x89\xec\xa2\xcc\x81\x8b\x1d\x97\xf9\xb4\xcc\x67\x40\xcc\x65\x0e\xfc\xf7\x14\xf8\x5a\x99\x7f\x28\xf3\xb3\x32\x07\xc6\xb1\x28\xf3\x04\xd6\x6a\x99\x03\xb5\x03\x3b\x59\x95\xf9\x79\x99\x7f\x02\x5e\x57\xe6\x9f\xcb\x62\x5a\x16\x40\x95\xf3\xb2\x38\x29\x8b\xd3\xb2\xf8\x50\x16\x67\x65\x11\x97\xc5\xa2\x2c\x12\x58\xcf\x65\xb1\x04\x2e\x53\x16\x45\x59\x9c\x97\xc5\x45\x59\x7c\x2e\x57\x61\xb9\x3a\x29\x57\x67\xe5\x2a\x2f\x57\x97\xe5\xea\x33\x48\x9e\xf2\x7c\x0a\x5c\xbe\x3c\x07\x7e\x13\x95\xe7\xc0\x7c\x56\xe5\xc5\xbc\x04\x4e\x7b\xc9\xca\xcb\xa2\xfc\x1c\x96\x9f\x17\xe5\xe7\x0b\xf7\xfd\xf1\x3e\xd8\xdc\xfb\xa0\x65\x28\x01\xdd\x69\xff\xeb\xbf\xde\xef\xff\x77\xf0\xff\x1c\x39\x6e\xf9\xed\x37\xdf\xbd\x1f\xbf\x9f\x8c\x76\x7d\xaf\x3b\x00\x31\x7e\x4d\xb9\xc9\x7e\xb3\x43\xc5\xf4\x7a\x28\xd7\x48\xcb\x93\x2e\x1a\xdc\x05\xe5\x3f\xf2\xa6\x62\xca\x49\xe2\x45\xb5\x0a\x15\x4f\x8b\xd3\x1d\xed\x93\xaf\x25\xbd\x71\xc9\x0d\x7d\x4b\x2f\x4c\x67\x65\xfa\x8b\x2c\xb8\xb2\x26\x60\x99\xf1\xb2\xc9\x35\x33\x05\x33\xfb\x67\x06\xd6\x39\x7b\x81\x3b\xa8\xd3\x34\x7e\xc9\x62\x11\x34\xc3\x77\xd7\x9d\x2e\x28\x72\xa0\x59\x7d\xd5\x4e\x1d\xe9\xa0\x6f\x31\x7c\x2c\xc4\x0d\x66\x6e\xf9\x3d\xb5\x5e\xe2\x6e\x0a\x6d\x2a\xd6\x76\x8e\x75\xb8\x8b\xde\xcb\xb2\x36\x20\x4d\x0d\xd7\x88\x7b\xf4\x22\x2f\xf5\x42\x2f\x47\xc7\x88\x17\x7b\x4b\x6f\xee\x9d\x7a\x33\xef\x9c\xb7\xb8\x08\x32\xe9\xe2\xbd\x0f\xe2\x01\x81\xe0\x51\x42\x5b\x2a\x62\xb4\xce\x82\x57\x3f\x09\x18\x0f\x07\x4a\xbc\x05\x07\x40\xb9\x6f\x17\xd0\x2e\x2a\xdf\xaf\x8a\xac\x73\xd2\x59\x74\xf3\xd5\x9c\x3f\xa9\x7d\x17\xb4\x8f\x1b\xfb\xae\x58\xf8\x4d\x80\xf0\xee\x01\x1a\x8c\xd3\x9a\x7a\x8b\x00\x2d\x46\xf8\x0f\x61\x0b\xdb\xed\x5d\x15\xfa\x52\x96\xa9\x7c\xe4\x22\xbb\x8c\xe5\x33\x59\x0d\x65\x99\xc8\x67\x61\x50\x94\xe5\x52\xbe\x11\xe6\x44\x59\xee\x36\xcc\x5f\x37\xca\xe9\x37\x47\x17\xc2\x77\xee\xaa\x8d\xf2\x55\x1c\xab\x60\x2a\xaa\xf6\x28\xcc\xdf\x24\xc7\x61\x8c\xca\xc3\x4c\x58\x79\x60\xef\x30\xa4\x99\x76\xdb\x61\xb8\xab\x45\x9e\x28\xdc\xef\x17\xfe\x9c\xbd\xbe\x8b\x83\x72\x31\x92\xdb\x9d\x99\x21\x3f\xdd\x43\x1c\x8b\x73\xb5\xd0\x51\x54\x3e\x13\xa6\x51\xba\xd6\x11\x6a\x89\x8b\x5e\x74\x98\x64\x8f\x3a\xa0\xbd\xaf\xbe\x8b\x01\xd3\x66\x63\xaf\xf9\xc0\xab\xcd\x09\x7c\x3c\xa2\x48\x5b\x3f\x32\x9a\x8d\x39\xfa\x2f\xa1\x4d\x49\x82\xfb\xef\x1f\xec\x9f\xe0\xd6\xf7\xc0\x6e\xfb\x05\x22\xb9\xda\x72\x42\xce\x6d\xff\x72\x2d\x23\xe3\xe6\xce\xd2\x9d\x13\xa4\xf3\xad\x90\x3e\xe2\x13\x52\x6d\x0f\x83\x87\xa1\x82\x0e\xdb\x91\xb1\x4a\xd2\x1e\x3c\x15\xc0\xe3\x1e\x91\xa0\xfc\xa3\xe0\x9c\x37\x2a\x7c\x5d\xdb\x97\xbe\x4b\x9e\x4f\xa0\xaf\x23\x82\xf2\xc8\x86\x72\x6d\x43\xf9\x26\xab\x4d\x0d\x90\x22\xfc\xbf\x14\x4d\x43\x01\x4e\xe8\xbb\xbb\xb9\x7a\x09\xfd\x81\x7e\x7c\xce\xe4\x97\xf3\x7f\x26\xd2\x4a\x2c\xb7\x2b\xb5\x1a\xfd\x85\xa7\xd6\xa2\x7f\xc2\x0d\x63\x7f\xb6\x5e\x7b\xdb\xe9\xb4\x69\x1f\x85\xb0\x76\xaf\x70\x0a\x4d\xb0\x14\xa1\xe9\xb6\x28\x6a\x44\x6e\xc5\x0b\x3c\xef\xbf\x77\xf6\x4f\x5c\xf2\x77\xca\x17\x2e\xbe\x88\x30\xee\x56\x46\xb8\x94\x25\x79\x34\xdb\xed\x4c\xbf\xa0\xa3\x24\xc3\x48\x2c\xae\xdd\x9e\x18\xd2\x6e\x9f\xfb\x11\x6c\x0e\xba\xc1\x7d\x20\xe2\x76\x37\xf1\xf5\x31\x98\xf8\x9c\xaf\x03\xc9\x3c\x84\xd5\xab\x0b\x8a\x02\x5b\x0c\x6f\x10\xd3\x59\xf4\x0a\x66\x7b\xc1\xae\x2b\x4e\xed\xff\x91\x66\x33\xf4\xe8\xde\x9b\xc3\xf2\xaa\x74\xe4\xe3\x06\xcb\xe4\xbb\x91\x6c\x60\xdf\x33\xd9\xcc\xa6\x78\x22\x26\x39\x96\x28\xfc\x46\xc2\x03\xdc\x45\xc4\x81\xac\x04\xcd\x3d\x00\x6b\xe4\x59\x5a\x3c\x02\x63\x48\x76\xfd\x3c\x7b\x90\x16\xb4\x47\xb7\xb9\xec\xbd\xe2\x09\x0b\xf3\xe2\x79\xc2\x24\xf4\x66\x85\x28\x7f\x5c\xc3\xaf\x26\x66\x60\x43\xa3\xdd\xbe\x0f\x13\xe7\x55\xe1\x6b\xa4\x2a\x63\x59\xda\x88\x75\x31\x6e\xc7\x72\xdc\x0a\x69\xd3\xfa\x10\x9e\x87\xf9\x14\x56\x47\xe1\x63\xe0\x36\xe0\xa3\x75\x7e\x6c\xbe\x58\x7b\xd7\x21\xa0\xb2\x5b\x29\x68\xcc\xd9\x2d\xca\x12\x9a\x93\x6c\xa5\x46\x1b\xdd\x02\xcc\x34\x42\x33\xed\xe4\xeb\x08\xab\x56\xb7\x05\x9c\xa1\xa9\xdb\x3a\x2e\x1b\xfb\xde\x29\xda\x6d\x36\x52\x92\x68\x33\xd5\x70\x10\x0a\xd7\x87\x15\xe1\x6d\x9f\x8a\x86\xfd\xcb\xdd\xdd\x42\x0c\x6f\xdb\x1a\x91\x7d\x18\xae\x3b\xbe\xf0\xfe\x99\xed\xed\x6b\x7d\xcf\x46\xbc\xf0\x26\xe7\xa8\xc1\x71\x79\x3c\x8f\xda\xd7\xde\xdc\xac\xb1\xb3\xdb\x58\xc6\x18\x2d\x89\xdc\x9a\xfb\xd3\xc0\xc4\x56\xb7\x2a\x56\xe6\xce\x60\x6a\x67\xd3\x18\xa8\x5c\x15\xfa\x7a\x73\x58\xaa\x48\x7d\x11\x33\x52\xad\xb4\x0d\x49\xbc\xac\x31\x2c\x21\x52\xbf\x76\x60\x42\xc2\xf2\xa1\x89\xb6\x36\xf5\x2d\xca\x6e\x19\x9e\x11\xaa\x61\xc8\x74\x19\x54\x22\x4f\x6f\xe4\x17\x11\x31\x08\xf7\x6a\x0a\x4c\x40\x1d\xe0\xf0\x25\x48\x45\xb1\xcc\xfd\xfd\x7d\xf1\x1e\xf7\x00\xf6\x45\xd5\xfd\x56\x87\x0d\xa8\x92\x3a\xe6\x51\xad\x75\x71\x71\xd1\x95\x1f\x6b\x55\x67\xfc\x08\x9d\x5f\x8b\x68\x7c\x93\x9c\x25\xe9\x45\xb2\x23\xa0\xde\x41\x6f\xca\x4e\x91\xee\x2c\xc1\xc6\xc0\xe8\x46\x6a\x02\x5e\xf8\x3b\x14\x01\x76\xed\x64\xb5\xfe\x4b\xcc\xad\xc4\x99\x31\x63\xa4\x52\x7d\xed\x7c\x91\xd2\xcb\x67\x8b\x87\x18\x6c\x9a\x2c\xae\xa3\x5d\x4f\x8a\x05\x8b\x25\x1d\xd6\xaa\xdc\x74\xb5\x1a\x83\x13\xba\xe8\xd7\x0e\x4f\xd2\x02\xe7\x28\x96\x02\xbb\x69\xf3\xc5\x2c\x74\xfd\x70\x9b\x88\x4b\x0c\x7f\x53\x4b\x1b\x66\xf8\x5f\x8d\xd5\x0c\x54\x80\x96\xb8\x1d\x0d\x20\x5a\xb8\x32\xa8\xac\x53\x82\x4e\xfa\xfe\x1d\xee\xf3\x1f\xed\x47\x35\x1d\x53\x56\xe0\xda\x8b\xfc\x0a\x8d\x2d\xf1\x84\xdc\x6c\xfb\xd6\x16\x74\xcb\xf1\x0b\x00\x6e\x58\xbc\x50\xc4\x0a\x24\xac\xaa\xa5\x52\x5d\x49\xad\x77\x4e\xed\x5d\x50\x08\xd3\xb9\x51\x49\x16\xca\x47\x55\xab\xae\xbc\x56\xa3\xc2\xe8\x4d\x05\x5e\x40\x33\x09\x13\x09\xb3\xe0\x35\x97\x0f\xf0\xa4\x68\x4d\x94\x6c\x8c\x81\x43\xad\xdf\xad\xdb\xe6\xfb\xed\x70\xb1\x1c\xa0\x6d\xd4\x6e\xb9\x5b\xa8\x82\x1a\xdb\x8a\xb4\x51\x0d\x3d\xbe\x53\xe9\x7e\x0b\xb2\x10\xbd\x81\x69\x45\xd8\x65\x38\x21\x61\xec\x87\x57\x35\x35\x2a\x35\xdf\x48\xaa\xe3\x85\xe5\xe9\x20\x8c\x01\x7d\x9d\x81\x70\x01\x83\xe1\x55\x1c\x62\x0c\x01\xaa\x3f\x76\x95\x1b\xc4\x51\xdb\x44\x4d\xc1\xd4\xde\x16\x88\x6f\xd0\x62\x23\xf1\xf3\x86\x1b\xc0\x6e\x68\xb0\xb5\x8f\xf6\x4c\x93\xb5\xc3\x51\x23\x0c\xc1\x9e\xb7\x87\x16\x2b\x67\x67\x74\x7a\x74\x3d\xf1\x6e\xd5\x8f\x57\xaa\xe3\xf7\x19\x9d\xe5\x00\x08\x8f\xf8\x5e\x48\x60\x3e\x94\x25\x9e\x05\xa1\x17\x8b\xf0\xd3\x93\x28\x07\x0e\xc0\x32\x59\xc6\x7c\x55\x96\xfc\x84\xde\xda\x38\xd7\xaf\x61\xaf\x1f\xde\x2c\x74\xc1\xd4\x28\xc8\xb9\x77\x63\xb1\xd0\x28\x56\x3d\xb7\x09\xeb\x56\x44\x10\x19\x15\x72\x63\x36\x38\x70\x88\xc0\xb5\x71\xc2\xd3\xcb\xba\x87\x38\xce\xc3\x05\xe7\xf7\xf8\x42\x1f\x5b\x90\x08\x11\x47\x0f\xad\x4f\x16\x36\x54\x01\x21\x99\x9f\x9a\x1f\xfb\x76\xcd\x9c\xd9\x9f\xcd\x89\xc6\xd8\x51\x44\x06\x58\x9b\x43\x50\xf8\xa3\xfc\x59\xf8\x0c\x09\x98\x0b\x7a\x64\x84\x42\xd0\x27\xfc\xbc\xc2\x31\xdb\x09\x41\xb8\xe7\x11\x12\xd4\x8e\x40\x9d\x1d\x3c\x5d\x99\x36\x19\x2c\x6d\x00\xc4\x60\xec\x16\x14\x2a\x58\xcb\x4b\xd1\xd9\xa5\x3c\x48\x8a\x24\xac\x47\x0c\x40\xf7\xc4\x91\x73\x44\x2f\x10\xe3\xae\xf9\xbd\x4b\x9f\xca\x32\x74\xea\x6f\x5d\xc9\x81\xad\xb7\x32\x38\x8a\xf0\xc1\x02\x75\x74\x66\xdc\x9f\x78\xcc\x3c\x9f\x47\xc8\x10\xc8\x61\x83\x2a\x92\xbe\x7d\x93\x4c\xc3\xd5\xc9\x69\xe1\xed\xac\x92\x7c\xc9\xa6\xd1\x3c\x62\xb3\x1d\x01\xea\x0e\xf5\xd8\xfd\xd6\x5d\xd3\xc9\x40\x13\x8a\x71\x31\xf1\x72\xb0\x16\xa5\xa5\xdf\x47\x0c\x44\xf8\x42\xa8\x7c\x0a\x22\x15\xc6\x85\xca\xdc\x4e\xdf\x37\x4e\x25\xba\x83\xe3\x8c\x85\x67\xa4\xe6\xed\x1c\x98\x5f\x3c\x73\x40\x56\xb1\x5b\x1b\x8b\x19\x0f\x07\xaa\x8e\x54\x03\x31\x8e\x2b\x0b\xaa\x40\x79\x29\x79\x83\xe8\x28\x0e\x9e\x37\xc5\xf4\x09\xfd\x41\x36\x5c\x0d\x56\x9d\x8e\x9b\x8e\x57\x7b\xfd\x89\x81\xdb\xd5\x64\x90\x98\x07\x96\x52\xed\x14\x0b\x71\xe8\x57\xff\x54\x2f\xd8\xce\x14\x43\x2f\x89\x5b\xa1\x23\x66\x2a\xdb\x5a\x05\x3d\x55\x75\x0a\x65\x2b\xf0\x28\xc7\x8b\x45\xbe\xe1\x6c\x26\xe9\x3b\x30\x79\x9c\x71\x98\x74\x37\x02\x9b\xaf\xbe\x88\x62\x51\xcd\x58\x4b\x8a\x4d\xb9\x37\xa1\x7a\x8b\x74\x01\x0d\x12\x0e\x61\xc8\xe2\xc2\x82\xa5\xaa\xdf\x63\x18\x39\x80\xd2\x95\x1d\xbb\x23\xfd\xdb\x67\x76\x7b\x40\x84\x23\x7b\xc9\xc0\x1b\x77\x54\x79\xc1\xc3\xe4\x98\x08\x44\xd4\xef\x83\x71\x95\xa0\xd9\xa4\x56\x86\x79\xf5\x0e\x2a\x0b\x12\xbb\xb8\x08\xb3\x84\xcd\x24\x3a\x93\x20\x77\xea\x8c\xc5\x1d\x35\xf2\x3e\xbf\x5e\xd2\x43\x2f\xdb\xb0\x27\x50\x64\x74\x23\x8e\xa2\x25\x52\x01\xab\x41\x00\x8a\x90\x27\xf3\x57\x30\x3e\x83\x4e\x92\xce\x98\xbb\x83\xdf\x31\x5c\x09\x59\x61\x1e\x1d\xc7\x6c\xc7\x64\xea\x3b\x0b\x10\xaf\xd9\xe5\x4e\x0c\x6b\x66\x67\xc6\x0a\x90\x1b\x6c\xd6\xdd\xf9\xef\xd9\x8e\xc4\x7d\xbe\x03\x44\x84\xef\xde\x00\xc1\x33\x5e\xab\xca\xa7\x1d\x17\x0d\xa9\x28\xc1\x50\x3a\x28\x15\x47\x50\xac\xdb\xaa\x4e\x99\x64\x08\x5e\x83\xc0\x93\xb0\xa3\x5d\xcf\xda\x6d\xeb\xd1\x71\xad\x83\x20\x36\x85\xa7\x49\xb0\x81\xe0\x2b\xc5\xa6\xac\xb2\x02\x94\x24\x4c\xa4\x8c\xe7\xaa\x86\xac\x8f\x39\x27\x60\x05\x02\x6d\x67\x88\x5d\xd6\x7c\x62\x91\x58\xe4\x57\xad\x21\xbe\x5b\x04\x0c\x54\x9d\x9f\x96\xe5\xc5\x59\xab\x2e\x41\x9a\xb8\x0d\x62\xc9\x86\xb4\x69\x69\x93\x80\xca\xff\xce\x02\xdf\xb5\x57\x78\x95\xf4\x5d\x63\x4a\x06\x8d\x62\x22\x55\x39\x04\x80\x8f\xed\xf5\x3d\x3c\x62\xce\x40\x70\x3b\x7a\xa4\x2e\x79\x95\xe5\x30\xd0\x21\x2d\x4e\x70\x56\xdb\xb2\xb8\x89\x3d\x7a\x8b\xa1\xd8\x9f\xe8\xec\x8a\xde\x13\xd1\xbc\x3a\x0f\xd2\x41\xbe\xb7\x37\xec\x0d\xf0\x0c\x65\x32\xce\x27\x1c\x36\xfc\xa5\xe0\x01\xd8\xcc\x47\xee\x2f\xcf\x82\x9c\x4b\x18\x9c\xf7\xde\x30\xb3\xd0\x80\xc7\xb5\xe4\x98\x47\x8e\xfc\x15\xf4\xbc\xe6\x51\xb9\x20\xd2\xc4\x69\xa7\xcc\xeb\xbb\x7f\x6b\x90\x9b\x57\x08\x2f\x7d\x2f\x8e\x9b\xd5\x2a\xa1\xd0\xd4\x66\xbc\x3a\xbf\xbb\x5b\xa0\x93\x65\x51\x85\xac\x0a\x41\x8b\x2b\x83\x64\xa8\x72\x5a\xcc\x50\xb2\x71\xca\x07\x22\x85\x43\x5d\xa9\xc0\x59\x64\x74\x24\xc8\x84\xb9\x8a\x1a\xee\x67\x36\x16\xb7\x89\x06\x23\xf3\xc0\xa6\x12\xd5\xf6\xec\x39\x0a\x84\xfa\xdf\xac\x25\x91\x52\xb4\x89\xaf\x70\x9a\xc4\x41\x0c\x54\xa2\x8d\x4d\x85\xc7\x89\xb2\x66\xf4\xa1\xee\x2d\x48\xb3\xa7\x3f\xde\x3c\xeb\xfa\xc8\x97\xd9\x4c\x4d\xfa\x8c\xa2\xba\xa8\xad\x8a\xd0\x9a\x00\x95\x2a\x8c\x3f\x9e\x20\x3c\x12\x8a\xfb\xe9\x2a\x29\x1a\x55\x11\xc9\x05\xc1\x56\xd3\x80\xa8\x06\x19\x41\x61\x3c\xba\xa3\xbe\x6f\x3e\x0b\x14\xf9\xbd\x35\x37\xea\x6e\x5f\x63\xd4\xc5\x01\x06\xa0\x4a\x1a\xc5\x0c\x26\x20\x73\xa6\x61\xe1\x4c\x5d\x7f\x89\xdc\x6a\xaa\xce\x2d\x46\x8e\x6b\xda\x6d\xdc\x12\x89\xa5\x6f\x01\x4f\xec\x46\x0b\x96\xae\x0a\x27\x73\x07\xd0\x6c\x6f\xa0\xb3\xae\xc8\x46\x06\x6c\x20\x19\xcf\xd4\x9b\xe2\x91\x8e\x4e\x67\x79\x17\x5e\xe6\xe3\xe5\x84\x32\x23\xb9\x03\xea\x55\x57\x59\xe7\x74\xe6\xdc\x23\x40\x31\xba\x31\x93\xdd\xa0\x73\xd2\x34\x0f\x11\x87\x84\x7d\x78\x29\x8c\x98\x6e\x88\x3a\x67\xc0\x4c\xfb\xd0\xbd\xa2\x5c\x6c\x39\x1e\x12\x51\x46\x1e\x50\x30\x82\xc3\x7b\x41\x08\x06\x2b\x50\xd6\x3e\xc1\x90\xa6\x67\x75\x82\x31\xd4\xd9\xea\x8a\x14\xfb\x8a\xd5\xd7\xc3\xbe\xab\x4f\x52\xf4\x07\xc9\xdd\x6a\x01\x3a\xc7\xce\xc6\x89\xad\x0a\x27\x93\xc1\x54\x9c\xe9\x83\x1e\xf9\x18\x5d\x2f\x2e\x4b\x03\xdb\x91\xd7\x03\x03\x3e\x35\x39\x1d\x8c\xdf\xca\xc1\xc0\x71\x22\x04\x37\x61\x53\x23\x07\xf7\x7d\xba\x45\x54\xc4\x2c\x68\x1d\x83\x6c\xcc\x91\x93\xae\xba\xe2\x27\x4a\xfc\x55\x97\x25\xe7\x88\xa1\x15\xd4\x38\x39\x47\x34\xad\xba\xe7\xb0\x92\xa0\x79\x0c\x66\x50\x0f\x39\x2f\x04\x6f\x43\x2c\x6b\xe8\xdc\x21\xbd\x06\xd5\x83\x7e\xcc\xe7\xf4\xb7\x22\xbc\xf5\x2b\x8b\x47\xe3\x6b\xb2\x3e\xf1\xc7\x71\x94\x60\x9c\xaa\x35\x23\x35\x07\xb7\x08\xd4\x90\x85\x77\xa2\x7c\x07\x13\xf7\x89\x60\x50\x36\x6b\xd1\x90\xa7\x17\x33\x13\x49\xca\x7d\x42\xdf\x4e\x67\x51\x76\xb3\x4e\xa8\xe8\x86\x2e\x56\x8b\x30\x3f\xab\x77\xb2\x23\xd7\xe6\x9d\xeb\xf3\x59\xd5\x52\x4f\xb5\xdb\xad\x55\xc2\x13\x58\xcd\x80\xad\x8b\xd7\xac\x92\x91\xea\x8b\xf2\x60\x65\x98\xc1\xea\xf1\x62\xb1\x2a\x42\x50\x8b\x9b\x13\x58\x59\x09\xfd\xd4\x62\xe2\x3b\xb1\x57\x98\x19\xc2\xcc\x20\xc5\x37\xd6\xc4\x99\x1c\xc7\x48\xac\x81\x2e\x27\x83\x4e\xcd\x14\x16\x86\x47\x86\x59\xfe\xb1\xf3\x30\x5e\x31\x5c\x95\x46\x09\x3e\x25\xd4\xab\xf8\xdc\x33\x58\x13\xb2\x35\xcb\xc1\x44\x30\xa2\x5a\xd3\x33\x12\x49\xa8\x34\x4b\x3d\x4f\x79\xc9\x18\x5a\x9a\x7a\x6d\x27\x2e\xcf\xe2\x40\x47\x95\x3a\x2e\x1e\x51\x0a\x8a\x71\xd4\x61\x2a\x03\x63\xd6\xe8\x9f\x32\xfc\x48\xdd\x3c\xfa\xcc\xd1\x83\x3f\x90\xa7\x1f\x45\x60\x38\x20\x5e\x72\xc2\x06\xbe\xb6\xbc\x57\xc6\xa6\x2a\x1b\x06\xbd\x51\x87\xf9\xd8\x74\x67\xa7\xc3\x4c\xa7\x95\xda\x12\x35\x7c\x69\x2b\x7b\xab\x9d\x34\x86\x42\xba\xdc\x78\xce\xb0\xbd\x64\x18\x14\xe8\x0b\x54\x20\x32\xbb\x00\xf4\x99\x18\xb8\x9c\x5a\x00\x2d\xa9\x03\x13\xd7\x71\xc3\x77\x66\x7c\x5f\x56\x76\xff\x35\x66\x46\x89\xdf\x1b\x16\x23\x63\x1a\x58\xa7\x70\x7d\x0d\xd7\xa8\xf0\xf9\xc7\x08\x83\xab\x0a\xa3\xd1\xb9\x81\xea\x05\xfc\x86\x92\xaf\x1d\xb3\xc0\xa9\x51\xe0\x84\x17\x78\x6c\x15\x98\x19\x05\x2e\x79\x81\x17\x56\x81\xf3\x4a\x17\x60\xf2\x1e\xf1\x72\x0f\xac\x72\x0b\x63\x73\x9a\xf6\xdf\x77\x8b\xf1\x79\x32\x31\x4a\x9c\x34\x94\x58\x58\x25\x2e\x1b\x4a\x9c\x58\x25\x8e\x2a\xe3\x29\xcb\x4b\x0b\x8a\xe3\x86\x16\x2e\xad\x16\x0e\x39\x13\xc3\x9d\x2f\xda\xab\xd0\x5f\x3e\x39\x32\x61\x28\xc9\x36\x20\x78\x9a\x1d\xe6\xf7\xc5\x2c\x8d\xe1\xab\x26\x78\xb0\xe1\xf9\x92\x8b\xfc\x2c\xb8\xa2\x9f\x7e\xe4\xcd\xe8\x50\x4b\x1f\x34\x1c\xdd\xf0\x85\xa2\x51\x51\x4c\x38\x40\x79\xd9\x9e\x21\xbb\xef\x9b\x3b\xfc\x4f\xad\x91\xbd\x34\x79\x01\xa6\xbc\xab\xbb\x88\x69\x44\xba\xc6\x2b\x2d\xa5\x9f\x1a\x47\xb4\x19\x9e\x8e\xe7\x7e\x33\xa3\xf9\xa7\x46\x2c\x07\x2c\x8a\x4f\xb0\x00\x8a\xf1\xa7\x64\x52\x96\xc5\xf8\x42\xa7\x0e\x6a\xe8\x16\x38\xae\x5f\xf5\x65\x3f\xaf\x00\x5b\x73\x53\x4b\x95\x46\xd5\x78\x6d\xd4\xe0\x99\x75\xf4\x82\x25\xf4\xbf\x01\x66\xce\x49\xbc\x5b\xa4\xaf\xd8\x47\x78\x7c\x64\x8d\xe0\xf1\x0d\x5a\x80\xaa\xbf\xb1\x4b\x36\xe3\xf5\xa9\xb9\x13\xbb\xcd\xa2\x3b\xcf\xd2\xc5\x61\x52\x64\x97\xfc\xc5\x43\xab\x93\x17\x37\x06\x53\xb4\xcb\x74\x4b\xd8\xc9\x63\x8c\x33\x91\xfd\xff\x6c\x35\xfd\x40\x37\xed\x7c\x71\xd3\xd4\x96\x4b\xa3\x28\xe8\x95\x6e\xf7\x4c\x11\xfc\x11\xd7\x01\x85\x42\x28\xd8\x70\x75\x22\x9e\x69\x42\x10\xd2\xeb\x8c\x5d\xd2\x11\x7f\xde\x06\x97\xc3\xb2\x91\x23\xfc\x28\xbd\x13\xd4\x22\xab\xb5\x78\x4f\x03\x40\x1c\x1f\x45\x6b\x13\x0c\x40\x6a\x15\x21\xf0\xa4\x52\x93\xc4\xa3\x67\xbf\xb8\x1f\x4e\x4f\x31\x2d\x84\xae\xf5\xa1\x81\x07\xbc\xb4\x78\xc0\x1b\xad\x81\xbc\x4a\xca\xd2\x79\xc5\x53\x32\x9c\x39\xe3\x89\x6b\x14\x7b\xa8\x51\xc1\x53\x34\x45\x39\x17\x87\x80\x7e\x5e\xbe\x70\xab\xe4\xf2\x52\x7e\x7c\xd2\xf0\xf1\xbe\xfc\x78\xaf\xe1\x63\x7d\x93\x86\x8a\xe2\x7c\x88\xf5\x45\x46\x37\x33\x32\x33\x19\xce\x9b\xc3\x4f\x4b\xf2\xd4\x71\x81\xbd\x93\x02\xff\x12\xb8\xde\xe1\xed\xee\x40\x8b\xe3\x33\x6f\xe7\x7c\xb2\x83\x84\x13\xb1\xdc\xc3\x52\x67\xb8\x1c\x44\x11\x4a\x6c\xab\xf9\x84\x46\xc4\xcf\x1a\x11\x9f\x91\x12\xfe\x2e\x1c\xc4\x05\xf3\x8d\xdd\x3d\xb2\xbb\x2b\xcb\xc6\xfd\x2b\x81\x9b\x7f\x08\x98\x9b\x23\xe3\xb3\xc1\x02\x9e\x9b\xa4\x60\xcf\xbd\x3d\xd9\x35\x0e\xf9\xb1\x2a\x6c\x40\x21\x9a\x22\x29\xd3\xee\x89\x3e\x6d\x8e\xd9\xa0\xa5\x3d\x45\x59\xa8\xd3\x61\x10\x52\xfe\x69\x91\x7d\x33\x1a\x27\xa3\x74\x2f\xf4\xc3\x09\xd6\x04\x65\x0a\xf7\x3f\xb2\x51\x3e\xee\x4d\xfc\x10\x94\x05\x2b\x8b\x63\xd8\xe9\x4b\xb7\x50\xa8\xfc\x43\x5a\x13\xc3\x2d\x20\x8c\xef\xa0\xa3\xe0\x1a\xd6\x3f\xae\x81\xb5\x11\x4e\xe3\xd8\xc2\xa1\x53\xdb\x7f\x37\xa0\x56\xa0\x75\x86\xe9\x08\x44\xa5\xff\x09\xba\xcf\x46\x05\x0d\x00\x1a\x2b\x70\xdf\x67\xed\xd6\xc1\x4d\xb3\x0d\xf0\xbe\x95\xe9\xf6\x4c\x5a\xb8\x27\x33\xef\x19\x05\x7f\xb3\xf4\xe3\xdf\xad\xa7\x77\xd6\xd3\x37\x2a\x43\x5a\xc1\x35\xc5\x62\x97\x36\xef\xd8\xae\xce\xb4\xb6\xcb\x17\x28\x32\x1c\x66\x6d\x86\x35\xca\x6a\x22\xbb\xe7\xf3\x46\x49\xce\xe4\x57\xd1\xa3\x2a\x4d\x29\x70\x98\xf1\xf4\x85\xd0\xac\x37\xef\x2f\x77\xd9\xc7\x55\x18\xe7\x1b\xe0\x91\x1f\x65\x31\x87\xb9\xa3\xdd\x1e\x2a\x3a\x0a\x45\xbf\xd8\x1a\xfb\xe8\x4f\xd4\x55\x3d\xb0\x8a\xaf\x5a\x2d\xbf\x58\xbb\xfe\xaf\x96\xb8\xfb\x53\x13\x95\xa8\x62\xf3\x58\x86\x22\x8e\xd4\x94\x0c\x4a\xbd\x80\x67\x50\x8e\x97\x9a\x92\xcc\x9a\xd8\x16\xfa\xb7\x31\x1b\xb7\xeb\xff\x55\xa9\xfb\xf8\x0b\xea\x1a\xeb\xfc\x57\x63\x9d\xd7\xd8\x3f\xea\x01\xd4\xe6\xaf\x28\x74\xd1\x46\x77\xb0\x63\xf8\xf2\xd8\xfa\xf2\x14\x7e\x80\x78\xd6\xad\xfe\x65\x6b\x46\x60\x0e\x99\xb6\x5f\x20\x64\xae\x29\xf7\xcd\x02\x06\xfe\x8a\xc2\x6c\x69\x38\x1c\xf6\xdb\xfd\xde\x0f\xb7\x7e\xb8\xdd\xff\xf1\xe0\x76\x79\xeb\xe0\xa0\x7f\x70\x70\xe7\xf6\x0f\xfd\xb6\x69\x4f\x16\x62\xdb\xbc\x20\xae\x50\x96\x4d\x7a\x86\x72\xdd\x5e\x4f\xba\x15\xd2\xdc\xda\xaa\xd5\x2c\x95\xec\xc9\x57\xfd\x81\x50\x3c\x45\x07\xd4\xb1\x52\x19\x75\x4c\x7a\xaf\x2c\xc8\x6c\x4d\x38\xb5\x3b\xc9\xbf\x83\xdb\x07\x3f\xdd\xfe\xe9\xfb\x1f\x0e\x7e\xba\xf3\x1d\x6a\x28\x43\xfd\x3c\x70\x8b\x7d\xe3\xb3\x07\x85\x75\xa4\x0e\x66\xfc\x94\x6b\x41\x65\xc1\x45\x43\x4b\x3a\xa9\x9e\x25\xa3\x84\xa2\x73\x33\xfa\xbf\x11\x0d\x18\xe5\x77\x3f\x9d\x61\x2d\xf9\x13\xe6\x3a\x2a\x2c\x32\xa7\x56\x84\x30\xfb\x90\x18\x57\x16\x68\xf3\x8e\x4e\x92\x50\x3f\xde\x13\xdc\x11\xb9\x87\x9b\x7a\x4f\x30\xc1\xe3\x87\x84\x36\x4e\x9f\x24\x9d\x8e\xf7\x81\xe7\xdc\xc3\x84\xa6\xda\xbe\x2f\xac\x8c\x31\x50\x23\x41\x2b\x5d\x25\x4c\xe1\xae\xb4\xe0\x56\xff\x3b\xb0\x28\x29\x12\x06\x81\xbc\x87\xa3\x2f\x7b\x06\x32\x4c\x3b\x35\xd2\x00\xe3\x3c\xbc\x48\x08\xbc\xa7\x09\x86\x2b\x21\x88\xca\x44\x66\x6a\x4a\xa9\x20\x4c\xdf\xf8\x2c\x99\x98\xdf\xcd\xcf\xbb\x8f\x13\x11\xa0\x40\x7e\x0f\xca\xd4\xf5\x38\x3f\x84\x59\xe6\x02\x19\x59\x4b\xd3\xfb\x6d\x6d\xb2\x20\xad\x82\xa4\xc4\x35\x7d\xee\x74\x1e\x24\x9e\x5e\x15\xed\x07\x38\x98\x07\x80\x23\xd7\x7b\x91\xb8\x30\xa6\x9c\x71\xc7\x8d\x3e\x67\x22\x9b\x7a\x0d\x45\x5f\xa3\x77\x85\xcb\xcf\x9a\xd7\xeb\x59\x9a\xec\x51\x80\x1f\xdf\x41\xe5\x3a\x43\xbe\x13\x66\x8c\xfc\x5f\xc0\x7b\xd2\x0b\xd0\x25\xc2\x1c\x95\x8a\xbc\xcb\x37\xd0\x00\x07\x42\xa7\xe6\x0e\x27\x95\xb2\xac\xf0\xce\x12\xef\x8a\xa9\x51\x53\xfa\xef\x34\x99\x47\x27\x2b\xf5\x7c\x91\x45\x85\xfc\xcd\xcd\x48\x66\x9c\xee\x51\x80\x7f\x19\x7a\xab\x0c\xc6\xf0\x49\x35\x15\x77\x37\xb4\xb2\x21\x4c\xf3\xe6\x0d\x6f\x48\xfe\xea\x6d\x26\x8a\x80\x55\x26\x8d\x86\x82\x3b\xdc\x28\xf4\xeb\x13\xf6\x26\x21\xbd\xaf\x48\x31\x49\xe9\x4e\x08\xb3\x04\x13\xa8\x5a\xdc\x91\xdd\xec\xa0\x03\x8b\xcf\x11\x5e\x66\xc2\x7b\x5a\xaf\xeb\x6a\x60\xaa\x78\x29\xe2\x56\xf6\x3b\xec\xc9\xa8\x17\x03\x16\x19\xef\xa2\x34\x98\x55\x82\x39\x0b\x1e\x3f\xe0\x71\x2c\x3f\xe9\x0f\xf2\x32\x03\x91\xe9\x04\x5b\xae\xbc\x52\x75\x0d\xaf\x41\x58\xe8\xfc\xad\x45\x6d\xe4\xe6\xe2\xa6\xd3\x00\x57\x58\x1e\x28\xa5\xbf\xdf\xf3\xe4\x5d\x2e\x30\x76\x60\x23\x0b\x9a\xb6\x9d\x50\xb8\x2d\xa2\xe2\x74\x27\xc4\x2c\x7b\x40\xab\xa0\x72\xed\xa0\x71\xd6\x35\xf5\xa7\x55\x61\xec\x35\x90\x56\xa6\xcc\xb3\x55\xce\x7e\xab\x9a\x86\x55\xf3\x6e\x5a\xd8\xf6\x5d\xc5\x2a\xb4\x0b\xc7\x5f\x52\x78\xf9\x25\x85\xe7\x06\x8b\x3e\x2b\x4c\x4f\x89\xaa\xcc\xcc\x9a\xf0\x34\x8f\xa3\x65\x13\xd1\xaf\x3d\xdc\x5d\xc5\x4d\x00\x6b\x4d\xc8\x33\x32\xe2\x93\x41\xec\x46\x5f\x9b\xda\x94\xb5\x30\xf7\x39\xc3\x0e\x40\xd8\x58\x17\x28\xa8\x82\x51\x32\x8d\x57\x98\xee\x0a\x0f\x67\x30\xf5\xd8\x5c\x18\x5a\x11\xe5\x48\x87\x7e\xc9\xf2\x55\x5c\x04\xcf\x70\xac\x35\x7b\xa0\x31\x73\x36\xed\xc6\xd6\x6d\x08\xad\x65\x15\xe6\x59\x27\xd0\xb9\xd0\x8f\x4f\xf7\x37\xac\x51\x5b\x37\xfa\xd1\x8a\x7c\xa5\x23\x62\xe2\x41\x70\xa8\xfb\x34\xea\x50\x91\x6b\xcc\x8c\x8c\x5c\x62\x8e\x88\x5e\xe8\xa2\xc3\x4d\xcf\x06\x31\x51\xb0\x32\x06\xfa\xa7\x7a\x0b\x36\x94\xfe\x09\x0c\x40\x4d\x70\xa3\x1d\x42\x50\x1e\x27\xa3\xa3\xc4\x3f\x4e\xf8\xe0\x0c\x17\x6c\x61\x9f\x06\xb6\x48\x2c\xb3\x08\x2b\xdb\x3c\xb7\x72\xba\x32\x94\xc3\xba\x48\xe6\x29\xfb\xab\x20\x09\x9d\x79\x73\x8d\x95\x14\xc0\x9a\x27\xa3\xc8\x57\x07\x7e\x53\xd0\x74\x0b\x6a\x66\xcb\x24\x9b\x8d\x5e\x3f\xc9\x91\x17\x2a\x38\x01\x13\xb2\x27\xfe\x01\x8f\x01\xcb\x49\x8f\xac\x7e\x9b\x26\xdd\x1a\x8d\x81\xde\xc3\x04\x3e\x6c\x9d\xea\x28\x48\x8d\xa9\x8e\xf8\x4c\x8b\x0a\x91\x48\x21\x1e\xf1\x09\xf5\xf2\x20\xc4\x59\x17\x5f\x3f\x41\xaf\xb9\xa7\xc0\x0e\x71\xea\x73\xc0\x11\x82\xeb\x5a\x6e\xdc\x59\x61\xa6\xc4\xb4\xa6\x31\x51\x9c\x22\xb1\x26\x34\x69\xe2\x06\x9a\x59\x14\xb4\xe8\x29\x27\x66\x75\xf5\x73\x22\x9d\xdb\xec\x68\x4b\x63\xd4\x00\x67\x11\xae\x97\xd8\x44\x62\x9a\x3b\x9c\x4a\xd8\x28\xf1\xf7\xfa\x7b\x74\x39\x96\x97\xd8\x54\x97\x54\xa9\x4e\x94\xa5\x92\xdb\x79\x8a\xc5\x80\x92\x2a\x63\x49\x34\xfd\xfc\x13\x0c\xa5\xe0\x77\x7b\x79\xbb\x1c\x32\x4d\x2e\x95\xc6\x1b\xd7\xab\xa8\x65\x6c\x73\x14\x55\x27\x87\xbd\x4e\x61\x92\x22\x1b\x4f\x86\x37\xa4\xb6\xf0\xa2\x5d\x5c\x78\xed\xf6\xee\xae\x22\xac\x48\xac\xbc\xe8\x8b\x16\xb0\x68\xa7\xb2\x7e\x47\x29\x9e\xec\x86\xa6\xb6\x2c\x62\x5c\x78\x22\xa3\x20\x69\x55\xb9\xf6\xc9\x6c\x40\x6e\xea\xad\x34\x7a\xf5\x32\xc6\xd7\x23\x27\x07\x13\x04\x37\x10\x33\xe8\x3b\x47\x17\x8f\xab\x7c\x5a\xd0\x91\x97\xaf\x0d\x68\x9a\x96\xb6\x09\x4e\x65\x69\x63\xf5\x2d\x0e\x23\x0a\x89\x19\x48\x24\x85\xc6\x32\x4f\xad\x65\x9e\x0e\x44\xfa\x68\xb1\xcc\xa7\xc1\x0a\xf3\x60\xc6\xf0\xa7\xcf\x7d\x63\x72\x4c\xb1\x37\xf5\xb4\x41\xfa\x09\x60\xcb\x46\x53\x1f\x47\x18\x63\xe0\x2c\x2e\xfb\xc8\xd8\xd8\xaa\xf0\xef\x0f\xd0\x7b\x37\xcc\x9f\xf2\x4d\x62\xf3\xf4\x48\x03\x56\x69\xd8\x59\x77\xb5\x9c\xf1\x0d\x60\x45\x0c\x29\xb2\x98\x5e\xd3\xa5\x63\x45\xa7\xbf\x76\xe9\xfe\xac\x30\x57\x7b\xd1\xa6\x43\xff\xa4\x02\x10\x6e\x07\x78\x51\xe0\xe0\xde\xd7\xe8\x02\x6d\x50\x04\xd1\x86\xb1\x11\xb8\x14\x39\x77\x54\x03\x0e\xf3\x36\x40\x8b\x4d\xa0\xa1\x4d\x3f\x46\xd1\x48\x91\x18\xd9\x68\x1c\x7a\xe9\xc4\x4f\xf9\xd1\x09\x1e\xc0\x98\x06\x0f\xcc\x85\x13\xd9\x9e\x17\xcd\x2d\x5e\xe3\x28\x52\x0c\x44\x5c\x9b\x3b\x80\xb5\x65\xc8\x39\x29\xce\xdf\x8a\x32\x4b\x44\x6a\xe2\x0a\xd1\xdf\x14\xde\x47\x48\x43\x84\x59\x4e\x19\xb0\x6e\xd2\xb2\xcc\xe1\x8f\x0a\x5b\xc3\xa6\xe5\x36\x8f\xc9\x9a\xd0\xa7\x46\x1d\x0e\x78\x76\xd1\x7c\x2f\x1d\xf4\x86\xc8\x95\x97\x81\xb8\xfd\x70\x6e\x33\x83\x39\xe7\xf1\x68\x71\x2c\x47\x4b\x5f\x6e\x6d\x2f\xa5\xbf\xc3\xdb\x05\x76\xf1\x81\xf6\x4a\x97\xc3\xa0\x07\x2d\xcd\xed\x45\x6f\x9d\x02\x0f\x42\x95\x70\x84\x51\xe9\xe5\x10\x5d\x0a\xc4\xa6\x3b\x98\xa8\xd4\x4f\x80\x1a\xe6\x37\xd2\xca\x78\x86\x76\x19\x23\xb7\xb4\x7c\x2e\x89\x19\xbf\x67\x23\xc0\x20\x0e\x52\xaa\xf8\x3a\xed\x01\x4a\x31\xe8\xe5\x5a\xc6\xa1\x07\x93\xe3\x2d\x4e\x41\xd8\xe9\xdc\x4d\xdd\x11\x47\x86\xef\xac\x60\x61\x31\x62\x1d\x89\xbf\x02\xd6\x11\xb9\xe2\x16\xaf\xd5\x2e\xc2\x08\x83\x5b\xad\x8d\xf1\x6d\xd3\x06\x61\x56\x6e\x32\x0c\xa9\x1c\x72\x94\x2c\x29\x6c\xcc\xfe\xe4\xf1\xe1\x5d\xc3\x75\x68\x20\x03\x37\x32\x78\x4e\xa7\x93\x0f\x15\x5e\x2f\xc4\x8d\x46\x45\xa0\x8a\x48\x79\x51\x96\x42\x27\x2c\x7c\xfc\x71\x94\x8c\xd0\xad\x8d\x9c\x53\xde\xd5\xc5\x1d\xdd\xf8\xc6\x54\x3a\x49\xe9\x98\x1b\x1b\xde\xdb\xb5\xc7\x2f\xd0\xe2\xc8\x57\x7f\x13\x12\xc0\x8a\x92\x04\xae\xd5\xfd\xf2\x26\x91\x81\xaf\xdb\xed\x4e\x27\x6c\xb7\x33\x9e\x93\x06\x67\x39\xfc\x12\xf5\xef\x0b\x20\xc6\x93\x16\x1a\xe4\xba\xe2\x48\x64\xbc\x71\xa2\xe9\x26\xd4\xfa\x84\x9a\x72\xa6\xb0\xe4\x4c\x31\x90\x8c\x89\xcb\x99\x55\x10\xa1\x9c\x99\xc2\x9f\xfe\x64\x50\x45\xc6\xd4\x5b\xc1\xe8\x47\x19\x99\x31\x40\x0c\xa8\x6e\xae\x48\xfe\xf8\xb0\x52\xd0\xad\x43\xb9\xd8\x2d\x45\xf3\x78\xbb\x2e\xf2\x25\x62\xdf\xba\xd0\x75\xeb\xac\x63\x45\x71\x8d\xe8\x8d\x16\x7d\xea\x4d\x2b\xcb\xde\xd2\x19\xa6\xae\xcd\x00\xa4\xee\xb0\xe2\xba\x03\x5f\xf4\x37\x57\x19\xbe\x60\x28\x30\xed\xc6\x58\x1a\x94\x8d\x15\x1d\x8d\xb8\x6e\x8b\x0a\xc6\x10\x0f\x66\x29\xf7\x96\xe7\x82\x1a\x3c\x9b\x14\x60\x95\x47\x72\x95\x47\x72\x95\x47\xde\x14\xc6\x6b\xae\x72\xfe\xc6\x5a\xe5\x03\x99\xc9\x9a\xde\x0d\xd2\x60\xc9\x75\x95\x25\x7e\x5e\x01\x3a\x57\x81\xa1\xae\xa4\x84\xb2\x8b\xd3\x08\x64\xf9\x4a\xd3\x81\xa6\x29\xd4\x27\x62\xc1\x3c\x0c\xd5\xe5\xd0\xb2\x58\x48\x4f\xc8\x02\x0c\xc5\x15\x91\xad\xd5\x7d\x91\x4a\x30\x11\x1d\x2e\x09\xe8\x4c\xa8\x5f\x04\xc9\x08\xf7\xc3\xfd\x9f\x9d\xda\x66\x48\xe1\x63\x04\x30\xea\x00\xdd\x79\x14\x63\x52\xa2\x86\x16\xb9\x6f\x92\x3c\x2f\xae\x14\x50\xea\xec\x9a\x5a\x5a\xf0\xa1\x6f\x7e\x10\xf4\x9f\xa1\xc1\x86\xec\x80\x6f\x2b\x00\x60\x98\xf9\x9b\x07\xff\xb4\xdb\x97\x8e\x56\x0a\xa2\x35\x67\x20\x7c\x53\x36\xd3\x16\xda\x28\x05\xcd\xd0\x0a\xff\xb8\xa4\xbd\x65\x87\xbf\x97\x71\x13\x78\xff\x6e\x0a\xc6\x54\x58\x14\x2c\x71\xf0\x30\x71\xca\xa5\x3d\x5e\x44\x3a\x5b\x4d\xad\x35\xc0\x7d\x6e\xda\xf5\xaa\x2e\x28\x56\x3a\x8b\x0e\x28\x53\x63\xec\x24\xeb\xb5\x87\xed\x1a\x91\x47\x7f\x8f\xc9\x6b\x9f\x24\x34\xb3\xe2\x8d\x4c\xf9\x9a\xd9\xc4\xb7\x55\xa4\xc9\x2e\x03\x49\x35\x5c\x01\x16\x69\xca\xa9\x85\x4e\xdf\xf5\x29\xce\x7c\x14\xf9\x20\x02\x61\x2d\x07\x5c\x60\x23\xc7\x02\xc8\x77\x73\x32\xe6\x0d\x2d\x41\x1d\x59\xc1\xfa\xbd\x2f\x64\xf5\x55\x46\x0e\xb2\x99\xae\x8c\xb9\x46\x38\xa7\x03\xe9\xe5\x49\x6b\xbc\x9a\x3b\xed\xc5\x7d\x32\x72\x91\xc1\x57\xce\x86\x69\x79\xa1\x55\x00\x1a\x17\xd8\x68\x8e\xcc\x36\x7f\x17\x13\xc2\xec\x2e\x60\x89\xa9\x94\x60\x82\x63\xa3\x6d\xb0\xc2\x65\x2b\xae\xdc\x49\x91\x4c\x56\x55\xc0\xf9\x11\x40\xb4\x51\x96\x29\xda\xe2\x5a\xa8\x54\x18\xfc\x45\x65\xbe\x2d\x8d\x59\x2b\xa9\xd6\xda\xe4\x96\x44\xcd\xcd\xc2\x2d\x09\x17\x97\x9e\xa6\x59\x23\xa0\x6c\x9b\xcf\xc2\xf0\x54\xb4\xdb\x07\xdf\xf1\x5f\x78\x2c\x67\x1b\xc5\x99\xaa\x39\x9d\x34\xbc\x56\x52\x64\x9a\xd8\x40\x27\x47\x65\x2e\x45\x81\xc0\xb5\x40\x3c\xef\x83\xd2\x44\xbf\x01\x4c\xb9\xde\xff\x49\x6d\x9b\x7e\x1b\x1c\x5e\x85\x86\x8e\xf1\xd3\xd6\x18\x04\x09\x4e\x54\x96\xe1\x7f\x1f\x60\x10\xa8\xf6\x1f\x79\xc2\x79\x84\xb4\xff\xdf\x07\xc0\xcf\x13\x0f\xd7\x00\x43\x46\xce\x7f\x4a\x3f\x12\x77\x10\x19\x3e\x84\x97\x6a\x5a\xf9\x75\x87\xf7\x0a\x79\xa6\x4b\x98\x68\x3d\x02\xb5\x71\x7a\x99\x46\xd3\x38\x83\x46\x22\xe8\x28\x19\xd1\x7b\x14\x22\x6c\xb2\xc6\xed\x64\xce\x72\xb5\x7b\xa0\x9b\xa7\x59\xb1\xd1\x41\x82\xf7\x3f\x24\xf0\x1f\x26\x7c\x1a\x1f\x4c\xf6\x12\xf8\x0f\x09\x25\xcd\x0e\x01\x99\x60\xbe\xd9\xac\x2c\xd5\x87\x26\x82\x83\xb5\x5f\xff\x18\x60\x28\x06\x5a\xa6\xa3\xc7\xb0\x02\x7c\xb1\x11\x0e\xbf\x1e\xc0\x7f\x46\xdc\xa1\x42\x03\x1a\xdd\x12\x13\x86\x9f\xe7\x7a\x0c\x40\x6d\x31\x72\x04\xb8\xce\x78\xf5\x30\x9f\x16\x18\x66\x80\x52\x33\xc1\x05\x8d\xb7\xc0\xaf\x4d\xaf\x0d\x4a\x0e\xed\xb2\xbd\xbe\x25\x78\xc1\xdb\x30\x42\x23\x2b\xab\xb5\xa0\x2b\xc8\x64\x1f\x24\xc7\x80\x88\xf9\xc1\x22\xbd\x17\x95\xa8\x7d\x70\xfc\x45\x12\xa0\x2c\xb3\xa1\x19\x24\x79\x03\xc7\x30\x17\x63\xc9\x46\x39\x2d\x25\x2a\xc5\x06\xbb\xa6\x5b\xb7\x72\xa4\xa6\x76\xaf\x97\xbd\x60\x18\x0f\xf0\xde\x75\x12\xe5\x33\x77\x69\x1d\x80\xed\xe4\x24\x92\xe0\x51\x8b\xc1\x4d\x0b\x5a\xa7\x03\xad\x88\x5c\xc7\xed\x0b\xcd\x33\x92\x8d\x23\x09\x30\x98\xd9\x7b\x05\x64\x69\x6c\x79\xf8\xa8\xd3\x88\xfb\x87\x8d\x83\x91\x4d\x1a\x9b\x3a\x30\x14\x02\xc9\x25\x41\xb4\x19\x65\x7c\x7c\x68\x91\xd0\x9d\x36\x0b\xd6\x5c\x0c\x87\x8f\x37\x88\x86\x22\x2a\x89\x73\x29\x66\x1e\x1e\xd9\x3c\x1a\x8e\x32\xa8\x5e\xe5\xfd\xaf\x0b\x2b\x4e\x06\xdd\x04\x23\x4c\xa1\x65\xec\x95\x5a\x5b\x76\x8f\xd5\x3e\xe3\xae\x8c\x0e\x71\x54\x8e\x83\x4d\xf1\x6e\xe3\xdf\xbc\x9d\xb7\x93\x9d\x62\xb5\x8c\x19\x0f\x64\x33\x42\x58\xcd\xc0\x11\xdc\x10\x24\x12\x02\x24\xdb\xd1\xa8\x66\x29\x0a\x38\x3d\xe5\x0b\x7e\xe6\x9f\x1b\xb1\xa5\x66\x29\xfb\xb0\x83\x43\x95\x1e\x0b\x2e\xe1\x3f\x70\x8d\xc3\x0f\x46\xb4\x69\x51\xd9\x32\x26\x2a\x32\x35\xfb\x91\xd3\xfc\x5e\xe6\x4d\xe1\x42\x4c\x17\x21\xbf\x3b\x51\xa9\xff\xda\x3c\x61\xa1\x6b\x1a\x59\x07\x8c\x20\x55\x7b\x5a\x8a\x21\x1b\xf5\x7d\x36\x2c\x46\x7b\x7d\xdf\x58\xb3\x4f\x8c\xbd\xc2\x57\x3a\xfa\x90\xac\xc8\xe7\xd7\xcf\x8b\x0e\x3f\x04\xd5\x09\x79\xf9\x5e\x1c\x9d\x89\x19\x1a\x60\x8b\xb8\x06\xdc\x86\xdd\xe6\x0f\x26\xa2\x1b\xa3\x83\xdf\x61\x04\xd2\x9b\x82\xeb\xe3\xf8\xd0\xc5\xfd\x5b\xf4\x00\x62\x03\xb9\xe5\x82\xe3\xda\x00\x2a\xf6\x83\x1c\x97\x37\x27\x80\x44\x49\x86\x66\x81\x42\xd1\x12\x09\xb7\x32\xcc\x60\x5a\x03\x34\x15\x6f\xfb\xc6\x8a\xb7\x7d\x68\xee\x13\xa7\x17\x09\xcb\x1e\x3f\x90\x5b\xb2\x22\x18\xd5\x3c\x99\xf6\xb3\x62\x8c\x4d\x15\x8e\xa3\x02\x16\x9d\xdc\x58\xc6\x4d\xf6\x3c\x30\x84\xf0\xa3\xad\x95\xa7\x74\xda\x70\x53\xdd\xcf\x5b\xeb\x9e\xb1\x4b\xcc\x95\x26\x6b\x4b\xc0\x8d\xfa\x1f\xbf\xb4\xfe\xa5\x59\xfb\x0f\xbb\xf6\x11\x9d\x20\x12\x85\x8f\xe4\xd6\x4f\x22\x9e\xf3\x22\x9c\x9e\xa1\xde\x93\xa5\x69\xd1\x6e\xff\x86\xeb\x98\x7e\x9b\x71\x90\x36\x4d\xd3\xf9\x06\x34\x33\x19\x45\x54\xaa\x62\xbf\x59\xc5\xae\x10\x2b\x7e\xc1\x6f\xab\xf5\x7b\xde\xd1\xd1\x12\xfa\xf6\x99\x11\x6f\xf0\x7b\xcd\x3f\x61\x2f\xfd\x87\xc6\x46\x88\x58\x9f\x68\xea\x23\x74\x30\x1e\x34\xfa\x25\x66\x12\x7a\xc2\xe8\xa9\x20\xa3\x9f\x21\x9a\x8f\x98\xbc\xa0\x6f\xda\xb1\xef\x0c\x2e\xf1\x33\x06\x6c\xff\x9c\x04\x00\x44\xcf\x0c\xd6\xfe\xa6\x10\x3b\x42\x52\x29\xe4\xd6\x00\xc7\x89\xbc\x18\xcb\x39\x4d\xd0\x1d\xc4\x9c\x59\xc2\x37\x0a\x83\x5f\x14\xe2\xbc\x42\x03\xe6\xf5\xa4\x01\x8f\xa1\x81\x78\x77\x15\x18\x3d\x9c\xa5\x6b\x5b\x35\x15\xba\x73\x07\x0c\x08\xfa\x44\x5e\x9e\x79\x82\x2c\x03\x98\x06\x37\x07\xae\x84\xd5\x31\x4f\xcc\x8a\x7d\xcc\x9f\x0a\x3c\xe2\x21\xf5\xae\x7a\x1d\x8f\xa1\xbb\xc9\xc4\xda\x63\x16\xdf\x46\xf2\xe0\x54\xea\x09\x78\x83\x88\x20\x26\xe4\x49\x6f\x83\x89\x41\x72\x3e\x44\x23\xc0\x53\x0a\xaa\x2a\xb1\x04\x23\x58\x93\x4f\xa1\x91\xa6\x59\xb3\x3e\x90\xbf\x72\x4b\xc0\x2a\xe0\x87\x7c\x78\x85\xef\x24\x60\x23\x81\x8a\x06\x68\xc1\x51\x7c\x44\xcd\x29\xf2\xc6\x50\xd0\x8a\x9f\xff\xd3\x0a\x51\xac\x04\x3a\x7e\x2c\x30\xde\xdf\x7e\xf7\xd9\x88\x55\xfc\x55\x11\x19\x9a\x8a\x34\x97\x72\x01\x81\xc2\xe5\x1a\x9a\xc0\xe7\x82\x00\x1d\x8b\x13\x11\x5e\x34\x11\x3b\x11\x20\xdf\xc9\xcd\x00\x20\xcb\xba\xbe\xfa\x35\x1c\x0e\x13\xb7\xbd\x4c\x80\x1c\x44\xa1\xcc\xcf\xd4\xcb\x55\x80\x83\xcd\x47\x63\x09\x46\x67\xca\x21\x99\xf8\x0e\x77\x2e\x7c\xe4\xbd\xa2\x7b\x71\x18\x8e\xc6\x05\x6e\x84\x00\x06\x8a\x89\xb5\x51\xfd\x33\x96\xea\xdf\xbd\x1b\x96\xf0\x1f\x22\xd1\x88\x04\x95\x03\x84\xe1\x15\x94\xe6\x0c\x2b\x64\xfa\xfa\x64\xd5\x0f\x14\xc3\x90\x3d\x0f\xa8\x03\xc6\x46\x96\x4d\x78\x57\x9e\xb3\x30\x63\xc1\xd9\x38\x9c\x0c\xd0\x7f\x21\xe6\xaf\xd0\x74\x9c\xd3\x9d\x70\xb4\xf0\xa5\xf1\x60\xc4\x92\x32\xbd\xa0\x65\xef\xdc\x5a\x41\xbd\xcb\x3a\x06\x08\x66\x39\xe6\xac\xf1\xa6\xea\xa0\xc7\x60\x3a\xcc\x07\x64\x20\xdf\xbd\x1b\x08\xa3\x3b\x06\x50\xf2\xc9\x40\x79\x3f\xe2\x76\x1b\xf7\x62\x68\x17\xb5\x0c\x56\x5e\x38\x06\x55\x6a\x12\xc4\xfa\x66\x32\x8e\x2b\x1e\x34\x60\x04\xac\x32\x93\x08\x34\x62\x6c\xb0\x62\x0e\xd7\x80\xfc\x2c\x04\x4a\x02\x13\x09\xb0\x84\x98\xc6\xa1\xdf\x4e\x46\x8c\xfa\x93\xc7\x28\xa4\x9e\x38\xce\x26\xb0\x88\xb0\x1d\x12\x1a\x69\xa7\x6f\x75\x9e\x30\x75\x4e\x5c\x74\xac\xae\xb3\x8e\xee\xaa\x33\xfa\x91\x44\x3f\x4c\x17\xde\xdc\x16\x06\xe8\x1e\x18\x2c\xe0\x3f\x98\xd4\x30\x08\x37\xa9\x88\xbf\xa0\xbe\xa5\xaf\xbb\x0e\x15\x2e\x22\xde\xaf\x19\xec\x9b\x99\x27\x41\xcd\x5d\x11\x63\x67\x9f\xce\x75\x2d\x58\x76\xc2\x1e\x30\xb6\xfc\x23\xc2\x83\xea\x78\x1f\xdb\xa8\xf2\x96\x84\xba\x0f\xab\x5c\xd4\xf7\x13\x83\xb5\x47\x6a\xcc\x72\x62\x40\x45\xbe\x99\x53\xcf\xeb\x99\xb9\x2e\x0a\x5f\x7f\xc3\x85\xae\x18\x59\x59\x62\xc6\x5d\x5d\x6e\x93\x9a\x52\x98\x68\x67\xda\x54\xa5\x21\x2b\x0e\x85\xbb\xe5\xcd\x3b\x95\xc4\xaa\x12\x5f\xc5\x09\xb8\x86\x45\xcb\x85\xac\xd0\x67\x30\x56\xa1\x61\x4e\x71\x32\xb5\xa9\x0c\xf5\x2b\x3a\x3a\x5d\x4f\x6e\x84\x03\xb2\xaa\x4c\xe4\x20\xc0\x1a\x62\xf5\x2d\x6b\x21\x8f\x22\x34\x35\xf1\xae\x3f\x98\x7d\x49\x95\x39\x26\xb7\x00\xf4\xe5\xeb\xb0\x80\xc5\x52\x52\x10\x20\x40\xea\xb5\x44\xa6\x5f\x0c\x28\x7d\x11\x16\xa7\x22\x61\x8c\xb9\xe1\x1d\x8d\xe6\xd0\x20\x6d\x1d\xae\x30\x8c\xc0\x8b\x03\x80\x6b\x2a\xf7\x37\x45\x0f\xa8\x3b\x4e\xa1\x87\x58\xb0\x73\x71\xd6\x1c\x58\xba\xef\x44\x5c\x8f\x2c\x5c\x42\xce\xca\x8b\x8d\x21\x86\xd6\x71\xe4\xbd\xa0\xa0\x98\xf3\xdb\xb7\xfa\xdf\xdf\xb9\xf3\xc3\xf7\x77\xbc\x22\x70\x7e\xbc\xf3\xe3\x4f\x3f\xdd\xba\x7d\xe7\xa7\x76\xe1\x76\x1c\x28\x70\xd0\x56\xaf\x28\xed\x20\xbd\xbc\xed\xb6\x0f\xee\x1c\x7c\x7f\xfb\x4e\xff\x16\xd4\xea\x60\x43\x3f\x8a\xbf\xfd\xef\xbd\xfe\xc1\x0f\x66\xcc\x7a\x5e\x41\x6c\x1a\x64\xe8\x6d\x37\x4c\x65\x72\x4d\x24\xa6\x3f\x75\x55\x9f\x0c\x31\xb5\x1d\x3a\x90\x01\x7c\x88\x75\xd0\xcf\xac\xb7\x97\x78\x1b\x45\x85\xf9\x72\xfe\x12\xe9\xed\xc2\x88\xf3\x3a\x37\xa7\x70\x71\x27\x45\x06\x93\xc0\xd7\xbd\xbe\xeb\xd3\x43\x31\xce\x3b\xfa\x50\x8b\x01\xd3\x54\xad\x2c\xe9\x05\x91\xc7\x65\x68\x73\x16\x20\x32\xe5\x5a\xc1\x5d\x88\x06\x40\x91\x99\x39\x4c\x9a\xc4\x98\x00\x8c\x9f\x06\x0a\x45\x24\x39\xe8\x16\x60\xca\x83\x1c\x00\x48\xc2\x4e\xaa\x20\x31\xb4\xa9\x98\x69\x1b\xe6\x9c\x71\xba\xdc\x76\x10\x80\x3c\xa7\x4b\xac\x64\x6f\x81\x25\xc1\x8c\xef\x28\x70\x03\xc2\x72\x88\x80\x49\xeb\xe4\x98\xff\xc2\xcb\x30\x7b\x55\x9c\x0c\xb3\xd1\x0c\xb3\x2d\x66\x1e\x08\x52\x6e\x3b\xc3\x70\xe6\x0c\xaf\x03\x96\x6e\x2d\x3c\x7f\xb1\x85\x1d\xd0\x32\x78\x05\x3d\x61\xb3\x0d\xc6\x8a\x1d\xed\xa3\x16\x37\x32\x59\x23\x32\x94\x35\x58\x2b\x7f\x58\xd6\xca\x9c\x19\xd6\x8a\x75\x64\x52\xaa\xad\x66\x74\x1f\xab\xe5\x8e\xb2\x19\x28\x3f\xc1\xcd\x73\xbc\xf8\x91\xf8\x68\x70\x76\x6e\x63\x71\x9a\x48\x48\xe7\x58\xb5\xdb\x2b\xde\xaf\x4f\x8b\x9f\x7e\xa2\xc2\x38\x4c\x47\x3d\x3f\xdd\x4b\x60\xa5\x87\x7b\xca\xdd\x31\x1d\xc6\xe8\xd1\x9e\x06\x28\x06\xed\x8d\x4d\xdc\x2e\x99\xca\x49\xfb\x3d\x11\x5b\x9b\x6c\xb4\xb7\x37\xf5\x81\xc7\x59\x6e\xb2\x62\x62\x8a\x01\x74\xd9\x48\x17\x3d\xe6\x07\x31\x00\x01\x36\x23\x00\x89\x86\xc3\x0c\x58\x8c\x13\xd2\x2f\xb7\xa3\xfc\x33\x31\x07\x29\xae\x82\x24\x43\x79\x00\xb4\x5c\x65\x4b\x11\x7e\x7b\x10\x0a\xbf\x1b\x3a\x32\xcf\x75\x82\x61\xfc\x53\x18\x44\x5c\x19\x44\x4a\x83\x88\xfd\x29\x0c\x02\x4a\x3a\x88\xb2\x71\x3a\xf1\xb2\x3d\xa0\xae\xa8\xe3\xa4\x77\xef\x66\x30\xeb\xeb\xb5\xda\x62\xe0\x19\x58\xbd\x90\x9f\x5d\x5b\x86\xd3\xa8\xb8\x84\x15\xfd\x09\xef\x50\xc5\xf1\x81\xb9\x15\x46\x2a\xff\x6d\x62\x1a\x05\x31\x98\x5e\xb1\x75\xd6\x7f\x66\xa8\x25\xb4\x39\x27\xf4\x2f\xdb\x0c\x7a\xab\xcd\x20\x79\x36\x76\x0f\xb8\xbd\x84\x25\xa0\xdf\x12\x96\x00\xaf\xcb\xe1\x5d\x01\x43\xc9\x85\x8a\x9f\xe1\x2f\x04\x0c\xf4\x94\xdc\xb0\x9b\x52\x7a\x22\xd5\x3f\xa4\x9f\x86\xdd\x94\x1b\x41\x6d\x4c\xdb\x4d\xbf\xa1\xdd\xf4\x1b\xac\x59\x5c\x85\x3d\x58\x85\xe6\xaa\x58\x48\x31\x79\x45\x89\x8b\x42\x9e\x65\x0c\x33\x24\x08\x01\xde\x1b\xea\xb9\xd9\xb2\x44\xa1\xd8\xe8\x98\xda\xe2\x02\xa4\x87\xfa\xc5\x31\x57\x44\x93\x4e\xdf\x15\xab\x12\xc5\xe9\x20\xe9\xe8\x79\x51\x5b\xea\x34\x58\xee\xd0\x27\xf4\x4b\x5b\x4d\xce\xcb\x10\x67\xcc\x98\x42\x77\x14\x05\x27\xb8\x79\x6d\x1b\x6f\x38\x33\x39\x70\x64\xfc\x96\x5a\xdf\xd4\x7c\xf2\x22\x9e\xb0\xea\x46\x15\x53\x8b\xa3\x9f\xaa\x0a\xf4\x5f\x6f\x6b\xcd\x08\x32\x41\x68\x26\x99\xa9\x3e\xc9\x10\x33\x64\xdb\x09\x33\xad\x30\x75\xa2\x13\x94\xd7\x8c\x1b\x21\xb0\xec\xf2\xbb\x62\xe1\x29\xe5\x64\xee\xec\x02\xbd\x2b\x3e\x9d\xda\x5c\x99\x12\x90\x02\xd3\x95\x8a\xb8\x5e\xb9\x20\x9e\xbc\x25\x62\x24\xc6\x3e\x69\xa5\x50\xb7\x12\xb9\x4b\x5c\x68\x68\xdd\x4d\x83\x4b\xce\xd5\xbc\xa9\xaa\x19\x2c\xbd\xa9\xd2\x50\x57\x66\x9b\x08\x02\xb7\x09\x61\x25\xe9\xaa\x1a\x3e\x18\x03\xf2\x21\x6b\x14\x7b\xfd\x91\x7c\x41\x82\xce\x37\x7a\xc2\xe0\x01\x23\x22\x8c\xd9\xe7\x0a\xa1\x6b\x2e\x2b\x0b\xc9\x8e\xa1\x73\x21\x4b\xd0\x74\xe5\x8d\xea\x5c\x53\x56\x12\x8e\x23\xa6\x76\x6d\x59\x8d\x94\x34\x81\x73\x5e\x80\x85\xee\x82\xd9\x26\xa7\x0f\x4c\x40\xf3\x16\x68\x49\xa2\x14\x95\x4e\x05\x06\xc0\xf4\x32\xcc\x20\x87\x4a\x33\x1f\x0e\x13\x73\x89\xac\x29\x98\xea\x9c\x56\x06\xaf\x3d\xb6\x14\x03\x5a\x04\x5a\x57\x26\x93\xd0\xdb\xc6\xc1\xd2\x0e\x86\xa0\xe8\x6d\x87\x51\xe8\xe3\x2a\x0c\x3b\x89\x9f\x76\x28\x89\x5b\xce\x27\x61\x85\x8a\xa5\xb5\xd3\x9e\x0f\x83\x95\x1e\x34\x65\x94\x72\xb4\xf9\x39\x55\xe3\xa2\xeb\xc2\xf9\x60\x97\x68\x66\x0d\xf3\xce\x72\xe0\xc6\x81\xc0\x3a\x18\x77\xb1\x35\xb9\xa3\xb1\x58\x23\xf1\x04\x27\x00\xd4\xa7\x69\x07\x06\xef\x2d\x3b\x01\xa0\x73\x4a\x17\x76\xe7\x1d\xa0\xa8\x14\xff\x5b\xe1\x7f\x21\xfc\xa7\xbb\x9e\x0b\xbe\x7c\x8a\x7f\x57\xee\xe0\x74\x48\x15\x61\x02\xb6\x77\x6b\xf7\x47\xcb\x61\xa6\x98\xca\x79\x30\x1f\x9e\x8e\x88\x02\x56\xa8\xae\x9d\x0e\xe7\x23\xd1\x14\x55\xf2\x67\x88\x93\x59\xbb\x0d\x1f\xda\xed\x70\x98\xb7\xdb\x33\xab\x7d\x4c\x11\x76\x89\xab\x27\xd2\x90\x2e\x82\xd8\x3b\x09\xa6\x83\x93\x21\xf4\x77\x82\x53\x2c\x6f\x59\x9a\xc3\xcc\x9f\xc0\xcc\x0f\x16\xc1\x42\x10\xc3\xe5\x04\xeb\xeb\x27\xdc\x41\x94\x4f\x58\x7c\x9a\x20\xa5\x04\x33\x94\x7a\xe1\x10\xa3\x40\xce\x83\x73\x58\xe9\x32\x19\x14\xde\x21\x82\x49\xae\xbc\x15\x5e\xfb\x3d\x0c\x4e\xdd\x7c\x2f\x38\x85\xd1\xc0\x7f\x53\x44\x70\xcc\x13\x84\x59\xb5\xf8\xfd\x48\x54\x2d\xd7\xc7\xc5\xf2\x61\x5a\x96\x80\x0f\x4e\xd0\x38\xab\xf1\x40\x5e\xb1\x94\x23\x28\x08\x39\x94\x3b\x02\xb1\x7c\x2a\x9e\x5d\x9e\x47\x17\x2f\x53\x82\x99\x74\x70\x46\xdc\xef\x8e\x00\xd9\x7b\xbc\x6f\x31\x1b\xe3\xa3\xc9\x1a\xed\xfd\x61\xca\x55\x80\x2a\x1c\x53\x2f\xdf\x5b\x62\xee\xae\x76\x1b\x00\xb0\xca\xc8\x11\x4e\xbd\x53\x2a\x42\x84\xb2\x87\x34\xb2\x87\x81\x82\x5b\xbc\x62\xab\xbd\xdc\x53\x6b\x24\xc8\x4d\xf6\x1b\xac\x14\x03\x0e\xa6\xca\x79\x16\x2b\xd6\x7e\x7e\x33\xd6\x2e\x6f\x32\x3b\x37\x73\xc9\x6c\xf4\x10\xd0\xb6\x78\xaa\x2d\xca\x54\x7a\x09\xc2\x20\x41\x45\x25\x07\xdd\x19\x38\x2f\xd7\x0b\x86\x11\xed\x40\xe7\xc2\x0f\xbf\x80\x2f\x20\xab\xf3\x20\xbf\xa1\xeb\x20\xd7\xae\x83\xa1\xce\xb3\x14\x68\x7d\x39\x82\xb2\x0d\x5e\x85\x4f\xa6\x41\x07\x2a\x7a\x01\x5a\x5d\xb1\xd7\x27\x4a\x84\xc9\x35\x5c\xd3\x17\xec\xba\xed\x87\x57\xc8\x6d\xef\x33\xbe\xfd\x80\x0f\xff\xb7\xb6\x1f\xee\x9b\xa0\xd1\x5e\x44\xbb\x7d\x6c\x6d\x65\xbd\xac\x59\x83\xb6\x9e\x76\x61\xe6\xe5\xaa\x3a\xae\x47\x1c\xa1\x7e\x0f\xdd\xd3\xb8\xef\x40\xae\x6c\x4c\x5e\xb8\xd5\x95\x6d\xec\x86\x1b\x3a\xd8\x3b\xd4\xc1\xde\x25\x01\x40\x84\x66\xb6\x87\xfa\x99\xa9\x86\x3d\xb5\x6d\x44\x4f\x84\x36\x40\xb7\x9c\xed\x63\xb7\xc8\xf2\x79\x70\xb0\xab\xf8\x3e\x86\x39\xf3\x8c\xab\xe4\x68\xa6\xdd\x28\xcd\xd9\x07\x21\xa7\xb2\x00\x95\x72\xf9\xfb\xe0\x3b\x1e\xd7\x34\x02\xc2\x0b\xeb\x1e\x1e\x43\xe2\xea\xf0\x26\xee\xc4\x43\x57\x4f\x16\x44\x56\x2c\xd5\xc6\x6d\x50\xdc\x7d\x77\xc5\xd9\x14\x79\x1c\xde\xd4\xc7\x80\x50\x33\x03\x89\x26\x42\x8d\x52\x60\x18\x3a\x19\x0c\x5b\x38\x2a\x68\xb3\x9a\xfc\x24\x22\x62\x65\x24\x22\x6e\xfc\x90\x88\x24\x17\xca\x87\xab\x93\x72\xaf\x84\x66\x8b\x75\x10\x79\x39\xde\x0d\xa7\x31\x04\x8d\x7b\x88\x07\x5e\x9b\xf2\x3c\x89\xba\xd8\x2d\xbe\xa5\x7b\x2f\x89\x4e\x65\x39\xfe\x2c\x0a\x0f\xb6\xf0\x26\xb9\x27\xc9\xe9\x27\xf3\xc4\x44\x36\xe9\x94\xae\xff\x92\xc7\xdf\x1a\x51\x02\xd7\x2e\xbd\x17\xb8\xf4\x5e\x8b\xa5\x87\x0f\xdd\x55\x92\x9f\x46\xf3\xe2\x5e\x25\xc7\xd3\xeb\x26\xdb\xf7\x1b\xcb\xf6\x7d\x7c\xcd\x5a\xf9\xa5\x79\x6b\xe7\x94\x85\xb3\xaf\xdb\xda\x79\x61\x2c\x8f\x3f\x71\x79\xfc\x99\x04\x00\x84\xb5\xb5\xf3\xe0\x5a\x14\x3c\x41\x14\x9c\x09\x14\x3c\xb9\x09\xf7\x39\xbf\x01\xf7\x31\x78\x4f\x38\x9b\x39\x55\xce\x73\xd6\x84\xce\x5f\x2d\x74\x3e\xb3\x95\xd7\x26\xea\x60\x16\x75\x30\x0a\xf6\x21\xed\x16\x9f\xd1\x8d\x8a\xfe\x03\xbe\x54\xb1\x3a\x5b\x2c\x8b\x4b\x4a\x26\x75\x04\x05\xce\x98\x15\x2b\x70\x8f\x99\xd1\x5e\xf6\xcc\xfd\x95\xd4\x22\xbf\x34\x6f\x4b\x24\x6f\x4b\x8c\x19\x64\x66\x6c\xd3\x13\x63\x9e\x0a\x4c\x81\x5d\x64\xc1\x3d\xce\xc6\xcc\xa9\xfa\x70\xed\x54\xfd\x8c\x53\xf5\x46\x4c\xd5\xcf\xff\x97\xa6\xea\x8d\x09\x16\xcd\x5b\x55\x48\x3c\xdc\x82\x3a\x96\xfd\x2d\xd4\xfd\x6c\xa0\x2e\x41\xd4\x25\x59\x00\xdd\xbd\xaa\x30\xff\x47\x26\x04\x9e\x71\x8a\x2d\x25\xde\x95\x9a\x57\x39\x28\x3f\x21\xed\x72\xee\x52\x30\x83\xfd\xdd\xdc\x20\xcb\x70\x43\x02\xcb\x81\x68\x48\x30\x16\x9e\x2b\x22\x95\xf4\x5e\x7f\xa0\x72\x86\x27\x36\xf9\x10\x65\x50\x24\xae\x5d\xbc\x18\x8b\x2f\x6f\x4a\xf7\x15\xe2\x2f\x91\xbf\xfe\x2d\x65\x4f\x0a\x8a\xb5\xcc\x5d\xbf\xc4\x03\x52\x29\xf9\xd4\xb3\x8d\x99\x30\xb3\xcc\x60\x23\xe6\x1e\x60\x66\x86\xca\x7c\xae\xb8\x4c\xed\x36\xc4\x13\x70\xf3\x17\xb2\x97\xe7\x14\x3e\x61\x04\xce\xf2\x25\x95\x59\x6c\xc9\xe8\xe0\xa3\x9d\x60\x93\xc6\x59\xd9\x95\xec\xf2\x77\xad\x97\x6c\x9a\x66\xb3\x96\xb1\x5b\x2f\xbd\x84\xd9\xe5\x15\x53\x14\xf9\x96\x51\xb2\x55\x47\x31\x74\x77\x3d\x15\xb7\x29\x5e\x19\x36\xdf\x5b\x51\x79\x53\x36\x08\x46\xd7\x65\x6d\xba\xfd\x8a\x4b\xff\xb5\x97\x9b\x45\xc4\xb9\x7e\x1e\xda\x25\xbd\x1d\xf2\x78\x3f\xa6\x3c\x40\x0f\x3e\xa0\x5b\x9e\x28\xdb\xc9\x68\x44\x5d\x99\xc1\x9a\x0b\x39\xba\x2b\xd0\x08\x0d\xd0\xf6\x32\x65\x1a\xb2\x73\x0b\x2d\xe8\x06\x45\x23\xf3\x04\x57\x3d\x75\x3a\x0e\xf1\x82\x7f\x50\x2f\xac\x2a\x5c\x44\x58\x95\xe4\x2b\xf9\xd1\x78\x59\x96\x18\x55\x04\x2f\x4e\xa8\xeb\x4b\xfe\x70\x49\x0f\xc7\xfc\xe1\xd8\x61\xf6\x55\x24\x66\xf6\x51\xcd\x4c\xf5\x48\xf8\x8a\xa7\xa4\x96\x58\x1c\x9b\xd1\x3e\x7a\x11\xe4\xa1\x43\x2e\x59\x17\x03\x31\x2e\x2b\xaa\x92\x88\x52\x17\x1b\x3d\x22\xde\x58\x12\x78\xbb\xfd\x8d\x13\xf1\xb0\x7f\x3c\xea\x5b\x96\xf8\x88\x61\x18\x18\x1b\x86\x77\xa6\x8a\x5a\x14\x6f\xc6\x5b\xe2\x90\x57\x92\xa7\xba\xe6\x2b\x31\x8a\xc6\xc4\x34\x46\xac\x13\x62\xd1\x0a\x9a\x12\x49\x33\x24\x17\x00\xfd\x72\x80\x9a\x2c\x0b\x52\x11\xcf\xbd\x8b\x1b\x1d\x46\x0e\x80\xc6\x00\x4d\x27\x19\xc9\x23\xe9\x7e\x34\xfa\x06\x09\x47\x1f\x5e\x75\xfd\x6f\x1c\xe3\x11\xc7\xa9\x8e\x82\x60\x14\x9f\xb7\xdb\x77\x75\x8c\x66\x28\xe9\x03\x7d\xdf\x46\x8c\x89\x5a\xfb\x8d\x0c\xee\x77\x66\x71\x38\x55\x9a\x32\x4e\x17\x0e\xed\x04\x6b\xea\x2f\xd8\x72\x27\xdc\x79\x19\x26\x27\x6c\xe7\xf8\x72\xa7\xd7\xa2\xbd\x28\xbc\xb5\xb6\x92\x85\xa7\xbf\xdf\x03\xf9\x62\x7a\x53\xfa\x3c\xf5\x6a\x78\x8c\x57\xdc\x78\xc5\x10\xcb\x25\xc1\x5e\xe2\xea\x38\x9c\x4c\x67\x43\x64\xc9\x4c\x45\xec\x60\xaf\x32\x5c\x87\xc6\x67\x24\x78\xa5\x9f\x53\x16\xc5\x8e\xc3\xf6\x0a\x77\x3f\xd9\xeb\xbb\x9d\x3e\xdf\x42\x55\x15\xb8\x0b\x5f\xb1\xfa\x28\x1b\x44\x3c\x76\xd3\x60\x24\xef\xf4\x02\xad\x23\xe9\x9d\x8d\x24\x51\x56\x5f\xd5\xc2\xd3\x97\x9a\xa9\x31\x8c\x9c\xb3\x80\x0a\xdf\x4c\x49\xdb\x04\x5c\xaa\xe5\x50\x36\x48\x6b\xc0\x7d\x63\xc9\x54\xbd\x83\x8b\x5b\x39\x4a\x32\x8c\x31\xc1\x0a\xfc\xb7\x96\x04\x61\x8a\x25\xa6\xa3\x95\x01\xe3\x9a\xe3\x3f\xbf\x48\x24\xb7\x7c\x75\xb9\x38\x4e\x31\x35\xd9\xb6\xaf\x95\x86\x0c\x17\xec\x2f\x15\xf7\xa2\x11\xbd\x62\x7d\x01\x35\xbf\x30\x72\x4c\xfe\xda\xb8\x21\xaf\xb4\xc1\x62\x43\x3e\x1b\x23\xfa\x63\x6b\x03\x7b\xd7\x37\x50\x98\x77\x9d\xa9\x1c\x56\x2a\x75\xe4\xaf\xaf\x9e\x3f\xeb\xf2\xd7\xd1\x1c\xf9\xa4\xe9\x77\x66\x86\x44\x89\x1c\xa3\x79\xbd\x8b\x65\xdb\x80\x18\x08\xd9\xf7\x31\x28\xd2\x0e\x87\xcc\xe4\x3d\x5c\x6a\x09\xe3\x0a\x92\x3b\x5f\x22\xad\x17\x72\x54\x4f\x1d\x3f\xc2\xb8\x4a\x30\xa6\xad\x04\xd0\xc9\x88\x55\x62\xd1\x33\x4c\x5a\x95\x75\x42\xe0\x3a\x94\xe2\x89\x24\x9e\x5b\xf6\xaa\x61\xe9\xa0\x31\x34\x15\x32\x9b\x53\x8d\x51\x21\xbb\x09\xde\x80\xfc\xa0\x77\x94\xf1\xb8\x85\xe9\x29\xa9\x98\xc4\xa0\xce\x20\x3b\xbc\x75\xfb\xd6\xc1\x4f\xfd\x1f\x6f\xdd\xb9\x85\x69\xf9\xf0\xd5\xdd\xbb\xfd\x3b\x25\xfa\x7c\xf7\xfa\x77\xbc\xdb\xdf\xf7\x7f\xbc\x7d\xe7\xa7\xde\x0f\xc6\xd7\x5b\xe2\xeb\x2d\xef\x0e\xbe\x75\x58\xe7\xd6\x8f\xdf\xdf\x3e\xf8\xe9\xa0\xff\xd3\xf7\x65\xcf\xfd\x77\x21\x8a\xfe\x1b\x8b\xf5\xbf\xf7\x0e\x0e\x6e\x7f\xff\xe3\xc1\xc1\x1d\xdd\x08\xff\x72\xcb\xbb\x75\xf0\xfd\xf7\xb7\x7f\xfc\xe9\xa7\xde\x4f\xf8\x05\x93\x78\x89\x3a\xe6\x8e\x7d\xe5\x6a\xe2\x7f\xb3\xce\xc1\xf7\x77\x6e\xdf\xbe\x75\xe7\x87\xef\x7f\xea\x38\xc5\xdd\xbb\xdf\x8b\x6d\x7a\x1c\x3e\xed\x3e\x24\x22\xd5\xa9\x71\x03\x1b\xba\xd2\xbd\x55\x12\xb4\xf8\x0d\x13\x2d\x6f\x9a\x04\x77\xbc\x38\x21\x9f\x6c\xe2\x2d\x93\x20\x06\xfe\x05\xac\x1e\x93\xde\x9f\x26\x32\x17\x32\x9e\xe4\x98\x99\x4f\x83\xc2\x39\xf5\xe6\xb0\xfa\x9c\x19\xff\x73\x8e\x7f\xe6\x78\x0f\xb5\x4c\x0b\xbb\xa0\x47\xf2\x2b\x04\x27\xfc\x13\x4f\x98\x1b\x5c\xd2\xd3\xbd\x3c\x4f\xa7\x11\x5d\x08\x18\x1c\xd1\x9b\xe7\xd9\x8c\xac\xca\x63\x78\xe2\xf5\xa0\x8f\xae\xac\x05\x1d\x75\x5f\xb1\x22\x38\x27\x52\x3c\x87\x31\xfc\xeb\x5f\x47\x47\x8f\x9f\x3e\x7d\xf3\xfa\xde\xcf\x4f\x0e\x8f\x1e\xbf\x3e\x7c\x49\x3f\x8e\xfe\xf5\xaf\x96\xb7\xa8\x7d\xff\xed\xf0\xdd\xe1\x03\xfe\xf1\xa4\x5e\xf9\xd9\x83\xc3\x3f\xe5\xe7\xcb\xda\xe7\xe7\x2f\x1f\x1c\xbe\x94\x9f\x8f\x30\x9d\xdb\x31\xa0\xcc\x3b\x4c\x82\x03\xef\x13\x94\xae\x4b\x6e\xce\xac\xda\x6d\xfe\xb7\x2b\xe3\xe9\xbd\x0b\x6a\x5b\x3e\xb6\xbc\xfb\x49\xf0\x09\xd4\x88\x8b\x64\x70\x68\xcc\x53\x91\xbe\xa2\xe5\x5e\xcf\x0e\xd2\x1a\x3f\x16\x75\x27\xad\xb5\x77\xd8\x85\x51\xbd\x0a\x8e\x12\xf8\xf5\xf6\xde\x93\x37\x87\xaf\x82\x63\xfc\x7d\xf8\xec\xf5\xcb\xc7\xf0\x70\x88\x0f\xba\xd9\x88\x2e\x83\x2b\x82\x4a\x57\xe9\x2a\x9b\x6e\xcc\xfb\x25\x41\xc1\x7c\x24\x46\xbd\xf1\x7d\xe0\xf5\xcd\x55\xd6\x40\x0e\xaf\x91\x1c\x5e\x77\xd3\x79\x43\x99\xd7\x26\x97\xf2\x5e\xdb\xb0\xb0\x8f\x1b\x5b\x7d\x7d\x23\x04\x89\xd0\xf3\x23\x05\x77\x0b\xda\xdc\xb9\x6a\x79\xad\x75\xab\xd2\x9d\x99\xd3\xa4\x81\xef\x53\x3b\x54\x46\x5e\x9a\x52\x3d\x49\xa5\x2e\xec\xa2\xc7\x40\x87\x02\x73\x47\x9a\x0a\x86\xa8\x45\xb7\x53\x79\x75\x63\x56\x7d\x78\x9b\x4e\x7e\x88\x21\x7e\xe4\xb2\x04\xd5\x24\x3c\x21\xd6\x58\x35\xad\x5e\x1c\x25\xea\xfe\x51\xa9\x5b\x38\x8f\xbd\xd7\xae\xf7\xd8\x42\xae\xf4\x06\x6e\x99\xe1\x17\x58\xeb\x45\xf3\x0c\xbf\xb0\x66\xf8\x85\xd5\xb4\xce\x9a\xbd\xb1\xf1\x17\x7f\x63\xa2\xc7\x30\xd1\x93\x56\xa5\xd7\x2f\x40\x67\x7f\x43\xd5\x9b\xa0\xb3\x4f\xe8\x7c\x80\x88\x79\xd0\x8c\x98\x07\x16\x62\x1e\x54\x48\xbf\xd8\x4e\xfd\x51\x8e\xdf\x3f\xc0\x2f\xce\x1c\x61\xde\x88\x21\x42\x87\x8a\x49\xbe\x20\xe6\xf8\xb2\xc6\xc0\x5e\x1d\xfe\x4e\xcc\x6b\x60\x90\x0a\x26\xd2\xa6\x3d\x11\xe7\xcc\x7b\xe1\x7a\x67\x06\x34\x56\x86\x0b\x4b\xec\x20\xce\xd1\x58\x28\xe4\x85\x7c\x7c\x9f\x48\xe4\xbd\x28\xdc\x89\xcf\xd6\x56\x53\xd7\x1e\x62\x0a\x8c\x76\x28\x00\x49\xa5\x1e\x8e\x28\x26\x2a\xe0\xf7\x54\xa0\x62\xe2\x80\xea\x36\xca\xf6\x22\x3f\x9a\x78\x11\x3f\x18\x62\xa5\x44\x8e\x74\xd8\x4a\xd4\x0c\x45\x6d\x1a\x6f\x02\x82\x56\xbb\x1b\x4e\x1e\xee\x44\xc3\x4c\x1d\x2a\x8a\x3c\x01\x61\xa7\x83\x41\x39\x94\xeb\x18\xf0\xfb\xcc\x7b\xec\x7a\xcf\x6e\x82\x5f\xf3\x02\x8b\x3a\xae\x79\x32\xc3\x71\x41\x48\x36\xdb\xb3\x92\x19\x15\x95\x15\x22\x52\x20\x42\x19\x43\x99\x46\x87\x99\xd5\xc4\x4d\xe7\x89\xb7\xa6\x4e\x9e\xa1\x6a\x4f\xee\x21\x85\xb2\x94\x42\xeb\x82\xd4\xdc\x27\xcb\x00\x2b\xd1\x5e\xea\xa7\x74\xf2\x1b\xe7\x31\x9c\x60\x66\x9a\xda\x0c\xa6\x3a\xa9\x75\xda\x0c\xdf\xd6\x19\xbc\x11\x70\x9b\xe6\xb3\x06\xaa\x82\xa9\x33\x8c\xd4\x14\x87\x1e\x02\x4f\x13\x6b\x80\x87\x17\x53\xf0\xb5\x74\x0f\xd7\xd2\xbd\x26\xc4\xbe\x69\x38\x4b\x27\xe2\x17\x6e\x94\xd5\x81\x0c\x3e\x73\xb4\xf2\x04\x12\x8c\xf7\x95\xbc\xd6\x05\x5a\x7b\xe9\x64\xae\xba\x97\x29\x1d\xec\x3a\x69\xc3\x39\xc0\xf4\xfa\x73\x80\x4d\x83\x68\x3e\x11\x78\xf3\x51\xa4\xd9\xb5\xc3\x20\x77\x14\x8d\xc1\x9a\xa8\x0b\x99\x02\x66\xfb\x04\x32\x9d\x27\x50\x79\x79\x70\xcc\x23\xc6\x17\x28\x9d\xfa\xe3\x87\x3f\xf8\xda\x7c\x82\xf3\xf5\xe4\x7f\x6c\xbe\xaa\xcb\x47\x29\x82\x59\xe5\x05\xdd\x7d\x20\x82\x97\x25\xc1\x0e\x38\xd7\xc3\x2b\x7a\xf4\x44\xd9\x1c\x6f\x60\x4f\x74\x62\x4d\xf4\x40\x12\x75\x6a\x1c\x9b\xc7\xfb\x7e\x60\xe9\x39\x61\xb5\x49\x7e\xf1\xa1\x9e\xff\x26\xa4\xfc\x8f\xcd\xff\x76\x94\x6c\x9a\x71\x74\xaa\x0c\x2b\x19\x26\x98\x42\x02\x4f\x14\x66\x26\xf9\x60\x03\x1a\xbe\xa0\x00\x39\x56\xce\xb9\xe1\x8b\xe0\xd8\x04\xdd\xab\x04\x6c\x9c\xb7\xdc\xb8\xf9\xcd\x7b\x8b\x7f\x7e\xe7\x7f\xde\xe1\x9f\xb7\x42\x08\xc3\x27\x25\x7c\xe1\x3b\x09\xe4\x77\xd4\xc0\xd3\xc4\x7b\xde\x68\x1a\x90\x27\x26\x5a\xac\xc0\x3a\xd8\x3b\x00\xd4\xab\x67\xc7\x48\x71\x7d\xe0\x8e\xd4\xfb\x8a\x9d\x5c\x60\xf2\x6c\xb0\x13\x7b\x25\x13\x78\xfc\xfe\xce\x9d\x5b\x77\xda\xc8\xf7\xf8\x2f\xe5\xaf\x4c\xc0\x54\x76\x9c\x82\xdb\x92\xf0\x3b\xf9\xce\x11\x86\x25\xd8\xaf\xdf\xc3\xaf\x1e\x1a\x8b\xde\x6b\xb5\x4b\x12\xe5\x87\x2a\x11\xb2\xf7\xd8\xbe\x70\x2d\xbb\xac\x9c\x0e\xad\xb8\xba\xc1\x62\x6c\x81\x79\x84\x59\xae\x77\x7b\xc2\x55\xae\x37\xd5\xfa\xeb\xb5\x83\xa9\x9a\x9b\x30\xf2\x07\x10\xde\xd3\x70\x39\xa0\x04\xd5\x4f\xf9\x05\x1e\xe2\x1d\x27\x15\xcc\xf3\xec\x9d\x41\x5d\xa0\x23\xe9\xf4\x46\x1f\xf2\xd1\x51\x6b\xb0\xc5\xf8\x72\xa0\x0a\xff\x0d\xbf\x5c\xde\xd4\x33\x30\xdc\xbe\xf7\xee\x81\xe5\x76\xe7\x8e\xa7\x33\x73\xc3\x64\xaf\x0a\x14\xd3\xab\xe2\xc6\x7a\x10\x3f\xa4\x7a\x22\xf2\x4e\xaf\xed\xaa\x5b\x45\x32\x55\xe4\xa2\xbd\x52\x8d\x08\x73\xb3\x1e\x28\xaa\xca\x52\x4e\xb5\xfa\x86\x84\xb5\x05\xcf\xef\xc0\x82\x19\xdf\x56\x40\xd5\x7f\x60\x35\x2b\x72\xfc\xe2\x09\xff\xad\x30\x08\x00\xe4\xa9\x7f\x9d\xcf\x16\x93\x99\xdb\xb0\xe0\x86\xcd\x26\x51\x0d\xa4\x7a\x5a\x28\xd5\x79\x23\x2c\xd9\x36\x58\x92\x0a\x2c\x18\xb7\x40\x13\xe1\x7a\x59\x05\x94\x4d\xca\x8d\x79\x8a\x7e\x50\x47\xb3\xc1\xcb\x4d\xc0\xb4\x43\xca\x0a\x53\x17\x67\x70\xd6\xbe\x93\x04\x6c\xf4\x82\x0f\xcf\xf5\x8d\xc4\x80\x91\x51\x38\xf2\x30\xec\x39\xf1\x31\x1f\x7c\x46\xe8\xab\xce\xe5\x46\x8d\x47\x39\x7d\x05\x3c\xee\x66\xc8\x37\xf1\xdb\x7a\xca\x80\xcc\x82\x79\xab\x8c\x8d\x34\x87\x55\x1b\x7f\x24\x63\x23\x92\xb1\x38\xae\xcc\xcf\x6a\xd9\x35\xcc\xc1\x69\x7d\x09\xd4\x35\x10\xc0\x53\x73\xe0\xf5\xc4\xa4\x8d\xeb\x47\x65\x28\xc5\x45\x34\xbd\xf1\x74\x4b\xfa\xeb\x6d\x9d\x70\x73\xeb\xda\x98\x60\x1c\x15\xe5\x04\xde\xd4\xe5\x56\xf5\x74\x13\xe6\xaf\x53\x69\xaa\xe8\xb6\x54\x9a\x4c\xab\x34\x9e\x54\x6a\xe2\xc2\x7b\xe0\x7a\xf1\x97\xf1\x23\x0b\x9f\xf1\x97\xe1\xf3\x6b\x70\xc9\x14\x26\x1b\x3b\xfb\x72\x4c\xfe\x1d\x2c\x2a\x0c\x56\x30\xb9\x24\xa1\xb0\x34\x01\x94\x1e\x9e\xed\x2c\x5a\x70\xa5\xb5\x5d\xf7\x1f\xc4\x24\x69\x5c\x57\x8f\xd1\x4f\x2e\x32\xd3\x2c\xcc\x3b\x8f\x9d\x6c\x44\xf2\xcb\xe9\xbb\x3e\xe3\xf7\x08\xf1\xe7\x1e\x3e\xf7\x26\x88\x7c\x8e\xfd\x46\x00\xff\x41\xec\x9b\x49\x5f\xb7\x2b\x67\xe2\x80\xa0\xa1\xac\xd2\x00\x33\xa9\xfa\x2f\x8c\x24\x60\xa4\xb4\x8d\x32\x39\x24\xcc\x0d\xa3\x9e\x31\xe7\x15\x0e\x99\xe1\xb1\x91\xea\x4a\x35\xbd\x7e\xab\x4d\x1f\xe2\x4d\x1f\x96\x9b\x3e\x3c\x2b\x80\x5a\x3e\x14\xde\x6f\xae\xf7\xc1\x2c\xf3\x25\x0e\x2c\xd0\x77\xb4\xa7\xf2\xc3\x17\x28\x22\x18\x06\x3b\xd2\x3f\x39\x52\x54\xde\x3a\x4c\x78\xc4\x2a\x0d\xe6\x9b\x1a\xfc\xc6\x10\xcb\xf5\x3a\xa6\x4a\x58\x03\x83\x9f\xe3\x7c\x8c\x5f\xcc\x93\x9c\xc6\x86\x5c\xb5\x45\x1e\x04\xd8\xc4\x97\x34\x18\xf3\xa4\x5a\x8b\xef\x5d\x58\xa0\x6c\x06\xa4\x06\xc5\x3c\xa9\x81\xc1\xcb\x5b\x23\x33\x04\x7b\xbf\xf1\xde\x73\x21\x29\xed\xfe\xf0\x92\x6e\xce\xd6\x1a\xda\xaf\xe0\x0e\x7b\x48\x28\xbd\x0d\x6e\xd9\x8b\x28\x47\xb1\x04\x52\xae\x71\x78\x4f\xf8\x5e\x98\x91\x1c\x5f\xa4\x25\x10\x7b\xf0\x59\xa5\x23\x8a\xfb\x6f\xa0\x34\x6b\xbb\x97\x08\xc5\xb7\xa3\x4b\x44\x66\x16\x9e\x0b\xd7\xd3\x94\x14\xe8\x7b\x95\x2b\xe1\x8d\xfc\x95\x19\x5a\x4d\xf8\xa0\xd4\x04\x36\x50\x74\x62\xb9\x49\x7f\x13\x83\x14\x2d\x9a\x9e\xd1\x7a\x7d\x3c\xed\x6c\xcd\x37\xe7\x26\x79\xc2\x33\xc0\xa8\xca\x5e\xdf\x60\x44\x1b\x29\x99\x9a\xac\x10\xd0\xf5\x0d\x56\x69\x8b\xe2\x7e\x9b\x68\x90\xb7\x2f\xb7\x7d\x85\x2c\xa9\x03\x80\xa7\xb8\xb7\xe0\x25\x63\x22\x44\xc4\xbd\x06\x37\xf2\x34\xf8\x57\xe2\x87\x0e\xa4\x6f\xc0\x11\x36\xfd\x3f\x8d\x27\xec\x63\x1b\xae\x30\x2f\x5a\xd3\x52\xbf\x60\xce\x4b\xc9\x25\xdc\xa6\x4a\x3f\x5f\x36\x33\x2b\xa3\x22\x6b\xa8\x6a\xc5\x30\x36\x0c\x9d\x9f\x25\x6d\x48\x1a\x8e\xc1\xcc\x50\x3d\xcc\xef\xf1\x55\xe1\xe0\x79\xfd\xa3\x23\x30\xa7\x57\x19\x7b\x8e\x0b\xad\x12\xd3\xc5\xd9\x47\xa5\x7b\xd5\xf2\x66\x89\xa1\x0e\x4b\x19\x0b\xd9\xec\x85\x27\x9f\xa8\xb5\xab\x6f\xc3\xde\xd8\xb2\xd9\x4a\x0d\x2f\x6a\x60\x9b\xeb\x0b\x7e\x50\xa9\x79\xdd\x26\x0a\xd9\xfb\x9b\xe5\xce\xd7\xa8\xf3\x3c\x95\x8e\x21\x12\xb7\x28\xa3\xa8\x41\xc3\xe4\x91\xc6\x20\x34\x23\xd2\xcb\x6b\x60\x18\xd8\x69\x94\x3d\x92\xcb\x56\x67\x08\x13\xb7\x28\xfe\x6a\x70\x57\xaf\x30\x59\xab\xeb\x57\xc8\x43\x85\x22\x99\xf1\xd6\xc4\x66\x09\xb2\x28\x07\x7d\x21\x78\xc3\x8f\x0a\xbe\xa9\x6d\xf9\x3c\xbd\xf7\x82\xef\x57\x3f\x4c\x02\x73\x1c\x83\x87\x09\xa6\x74\x42\x96\x0d\xbf\x56\xf0\xeb\x61\x22\x04\xb1\xa7\x7e\xc1\x9a\x87\xdf\x52\xd0\x7a\x0f\xb7\xe9\x22\xd5\x5c\x23\x6a\x1b\x14\xef\x25\xe5\x67\xdb\x23\x95\xe0\x64\xc8\xf7\x05\x40\xb7\xfb\x06\x33\x5e\x8e\xd3\x09\xe6\x5e\x50\xee\x4c\x7c\xee\x1b\x17\x91\xdb\x3d\x37\xc9\xe9\x4c\x27\xbd\xd1\xa7\xdd\x78\x76\x1b\x3c\xeb\x66\xc2\xb2\x04\x58\xe6\x41\x2c\x61\x99\x63\x62\xf8\xdd\x6f\x9c\xd4\x8b\xc7\x4b\x02\x63\xb0\x04\xd0\x08\x9d\xc0\x4b\x87\x4b\xd4\x40\x4f\x47\xf4\xb1\x8f\x47\x23\x43\x7f\x6a\x9a\xda\x74\x4a\x03\x93\xe7\x38\xd3\xb2\xdc\x3d\xa5\xec\x97\x98\x5c\x68\xca\xd3\x62\xc4\xca\x2b\x89\x0e\xed\x53\xe8\x6a\x8a\xa7\xdc\xc4\xa5\x74\xc1\x23\x75\x08\x97\x92\xc7\xf0\xc4\xc0\xf2\x98\x1b\x50\xae\xa4\x25\x19\xfe\x79\x1e\xcc\x46\xb1\x1f\x39\xb1\xe2\x37\xa7\xa3\xe9\x08\xcf\x79\xce\xf7\xfa\xa3\x73\x71\x68\xe2\x1c\x80\x0d\xac\x07\xca\xe4\xe3\x9f\xf3\xd3\x45\x3c\xad\x8f\x37\x13\xe2\x5e\xa6\xbd\x3a\x17\xc2\x5b\xa6\x31\xc2\x83\x51\x6b\xef\xe7\xeb\x27\xbd\x12\x72\x47\xa9\x6d\xa4\xb2\xde\xbf\x7b\xd7\x71\xe4\xb5\xdb\xe8\x75\x2c\x30\x1b\x0f\x66\x3b\xa0\xbe\x79\xea\xaf\x81\xa1\xa0\x38\x69\x3b\x72\x47\x19\x67\x68\x94\xcf\x6b\x1c\x32\x7c\xb9\xd7\x77\x27\xdc\xcd\x86\x99\x7b\x84\x97\xc5\x06\xaf\x51\x83\x33\x0e\xe3\xaa\x20\x40\x0a\xf9\xc3\x70\x46\x57\x66\x95\x76\x78\x8c\x5c\xe2\x63\xa2\x19\x26\x32\x06\x51\x86\x9f\xa9\x09\x29\x10\x13\x46\x22\x3a\xd3\xf6\x8a\x6f\x51\xc4\xed\x76\x64\x27\x83\x42\x9a\xc0\x36\x97\x01\xc0\x0d\xe5\x00\x6e\xa0\x37\x3d\x1c\xef\x34\x88\x47\x73\x98\x14\x75\x69\x38\xa6\xac\x3a\x45\x96\x87\x03\xd3\xf0\xd2\xe1\x45\x68\xfb\xb4\x4a\x6e\xd8\xe9\xac\xdd\x9e\x2b\x2a\xfa\xac\x7a\xa7\xf4\x3a\x73\x3c\x91\xe7\xcd\xa8\x01\x28\xba\x0b\x65\xd1\xc3\x2c\xcb\xb7\xdb\x7f\x16\xce\x7c\xdc\xff\xf7\x52\x2f\x39\xfe\x28\x2a\x40\xf9\x7e\xb5\xfc\x4c\x15\x9d\xf1\xc8\x9b\x46\xf2\x5c\xc0\xd0\x66\xa3\xa9\x3f\xfd\xf7\xca\x9f\x96\x2b\xef\x84\x9e\x73\xe0\xb7\xde\xd2\x9b\x01\x41\xf9\x53\xfe\x1b\x7e\xad\xf4\x5b\x39\xff\xe7\x82\x22\x45\x42\xb8\x85\x99\xd4\xed\xc4\xa0\x4e\xca\x2b\xb4\xf0\x4e\x60\xfe\x1f\xfd\x3d\xf2\xac\x93\xa6\xa4\x4c\x4e\x7a\x91\xde\xff\x1b\xa5\x55\xea\x43\xc5\xfb\xd1\xff\x24\xfd\x71\xca\x92\x14\xc8\xa9\x27\x0e\xa6\x98\x88\x09\x4f\x40\xc1\xd4\xc6\x0d\x64\x07\xd4\x14\x37\x53\xd3\xd2\x4c\xbc\xa0\x6a\x08\xe2\xa4\x44\x7a\x44\x01\x9c\x57\xe1\x51\xcd\xf9\xde\x9e\xf7\x31\x19\xce\xf5\x49\x6a\xa4\xaf\x29\x50\x58\x2e\x4e\x53\xcd\x3b\x1d\xc1\x2a\x9b\xe8\x61\x16\xe4\x98\xad\x06\x98\xae\x77\x6a\x70\x2c\x47\x77\x18\xcc\xcd\x49\x9e\x19\x93\x4c\x19\x9c\xe6\x40\xc6\x6b\xef\xf3\xff\x9a\xe0\xf9\xfc\x05\x82\x47\x4d\x2f\x26\xc5\xca\x70\x7a\x53\x31\xbd\x52\x14\x91\x33\x63\x57\xe0\x48\x64\x2d\x93\x7d\x4f\xb9\x96\x60\x24\x62\xfb\x55\xeb\x42\x98\x0c\x8d\xe7\x62\x53\x3b\x7d\xff\x2b\x52\x6d\x2a\x38\x89\xb9\x29\x4b\xe9\xcc\xcc\x11\x41\x97\xc4\x5b\xfe\x3f\x20\xc6\x3e\xd7\x60\x03\x99\xe6\x7d\xbc\x9e\x9c\xa4\xff\xc1\x49\x8c\xd4\x8e\x88\xc6\x91\xf1\xd8\x9f\x20\x07\xf8\x78\x3d\x89\x88\x8c\x7b\x32\x7d\x79\x2a\x97\xf5\x37\x4e\x54\x69\x5e\xa0\xc3\x99\x8e\x52\x89\x33\xd5\xd7\xca\x55\x24\x02\x53\xb1\xe2\xd6\x3f\xe6\x68\xf0\x81\x76\xea\x48\x36\xd0\x82\xd5\x31\xf5\x85\xc2\x4b\x7d\xce\xc6\x00\xe3\xc4\x15\x39\x1f\x4c\xca\x03\x32\x8e\x5c\xf1\x19\x8d\x24\x4b\x15\x93\x1a\xf9\xe7\xa6\x97\x5b\x23\x48\x24\xdd\x82\xca\x8e\x89\x70\x8c\xd4\x49\xc3\x20\x1b\x64\x66\xa8\x4f\x84\xfb\x08\x13\x6b\xc7\x1b\x23\x51\x7f\x6e\xea\xf3\xd1\x17\x03\xc2\xb9\xea\x66\x30\x54\x26\x38\x09\x08\x25\xfd\x6a\xb7\x53\x65\x4b\x60\xab\x15\xe0\x2a\x54\xb1\x35\xee\xac\x30\xe6\x89\x9c\xcd\x7f\x14\xde\xa1\xeb\xfd\x61\x36\x80\xce\x52\xd3\xdc\x92\x63\x28\x84\xa5\x81\x85\x3c\x19\x56\x48\x89\x44\x07\x72\xdb\x1f\x37\xb6\x18\x8d\x12\x06\x88\xbb\x2a\x33\xf6\x09\x78\x36\x72\x22\xd1\xe7\x95\x38\x52\xa3\x52\x67\x51\x96\x51\xf9\x55\x1d\xb8\xcd\xe4\x9c\x89\x83\xb7\xea\x59\xc7\xd5\x24\xc3\xc6\x46\xa0\xcc\x58\x98\x3b\x7c\xa3\x70\x94\x50\xf4\x96\x6e\x9b\x72\x54\xe3\x44\x54\xda\x92\xf9\xc1\x84\x34\x6e\x6a\x84\x5f\x22\x42\x67\x17\x04\xc4\x26\x00\xf2\xdd\xc0\x42\x4e\xf0\x1b\xa6\xd0\x04\x0b\x73\x9a\x26\x45\x94\xac\xd8\xda\xfe\x6c\xfc\xee\xf2\x6c\xa9\x66\xe6\x7f\xe2\x6b\x3f\x27\xde\x23\x0c\x93\xde\xbf\xed\x7d\xa6\xbf\x07\x20\x28\xe9\x79\x00\xe2\x97\x79\xbf\xbb\x5e\xcc\x9a\xc3\xff\xb0\x75\x2b\x02\x30\x36\x8e\xab\x7f\x91\xa7\x18\x6f\x29\xd7\xb1\x8e\x56\x33\x75\x57\x31\x9d\xf8\x52\x11\x7a\x5e\x6f\x88\xe9\x3a\x87\xc6\xf9\x0f\xe5\x80\xc7\xc4\x6d\xd4\x95\x91\xca\x27\x09\x8e\xa4\x23\x4d\xbb\x8e\x40\x2a\x88\x0c\x11\x05\xe6\xb9\xa8\x80\xb0\xd1\xb9\xbc\xb0\x5c\x72\x56\x9d\xcd\xae\x60\x82\x48\xc4\xc1\x71\xa5\x8d\x43\x8e\xc7\xa2\xf1\xf4\xac\xe9\xdb\x04\x19\x42\xbf\xb9\xe4\xe0\xaf\x97\x94\x3f\xa6\xf0\xfa\xd2\xdd\x62\xf5\xfb\x8f\xb8\x4c\x4d\xa4\xa9\x10\x5f\x91\xb2\x42\xfa\x4a\x45\xd6\x8a\xc4\xf4\xae\x8a\x35\x8c\xa9\x2b\xbe\xd4\xd1\x7a\x4e\x97\xc8\x5a\x43\x41\xd9\x58\xdf\xf9\xd7\x1e\x3a\xa6\x07\x64\x39\x4b\x36\x1c\xda\x4d\xdc\xab\x63\xbc\xeb\xb5\xe7\xe1\x8d\xe3\xc2\x98\x1d\xe8\xec\x18\xbd\x41\xa6\x6f\x27\x47\x86\xc9\xef\xe0\x66\x9d\xcc\x2b\xc6\x19\x0f\x91\xb3\xe1\x4b\x9b\xdc\x9d\xc7\x82\x26\x7a\xde\x5e\xbf\x5a\x43\x1c\x7e\xdf\x32\xa8\x9b\x0c\x84\xd1\x40\x98\xb7\x57\x1f\x45\xd3\x1d\xeb\x32\x39\xc5\x38\x69\x18\x43\x0d\x9e\xca\x28\x6a\x43\xd8\xe4\xfd\x3e\xdc\xec\xfd\xae\xd7\xff\x0a\xef\xee\xe1\xe6\xa5\xb6\xcd\xf9\x7c\xb8\xdd\xf9\xdc\xdc\xce\xdf\x00\x4f\x3b\x9f\xab\x1c\x04\xb3\x9d\x34\xb1\x03\x4d\x2f\x45\xad\x16\xae\xf4\xcd\xfb\x96\x26\xe1\xaf\xc4\x16\x0c\x5f\xd9\xb2\xcd\x29\x4f\x96\x16\x53\x60\x47\xb5\xf5\x6b\xb6\x46\x7b\x18\xd3\xc2\xe4\xfd\x7f\xd7\x05\x29\x1a\xdb\xd0\x01\x66\xcb\x53\xf1\xa5\x09\x5d\x50\x52\xa3\xbb\x9b\xdc\x05\x81\x8a\x8c\x01\x01\x5e\x9c\xe0\xb8\x2e\x25\xe3\xa3\xab\x1f\x28\x54\x80\xb8\x47\x25\xd8\x33\xab\x75\xf6\xd5\x9e\xce\x99\x8c\x95\x91\xb9\xd3\x2c\x66\x68\xb2\x42\xcb\x0f\xaa\xf8\xe0\xcd\x5c\xa2\x1c\x3b\x51\x8e\x62\x30\x58\xf2\x8d\xe3\x3f\x6a\x1e\xd0\x27\x8f\x5f\xbd\xe6\x2e\xd0\xb7\x20\xa0\x8d\x01\x0e\xde\x26\x98\x27\x12\x99\xe9\x5b\xee\x02\x7d\xab\x5c\xa0\x6f\x13\xb1\xcf\xf9\x50\xfc\xc0\x37\x6a\xc7\xf1\xad\xed\x20\x95\xbf\xb1\x8c\x30\x00\x1e\xca\x5f\xfa\x1d\x2f\x2b\x7f\xe3\x7b\xb9\xff\xf4\x50\xfd\x54\x6f\xc5\x8e\xcb\x43\xeb\x11\xbf\xda\xdb\x12\x0f\x2b\x2f\xb0\x84\xde\x39\x78\x68\x3c\xf0\x2f\xda\xf7\xff\xd0\x7a\xa4\x96\xb5\x63\xff\xa1\xf9\xe4\xcd\xeb\x02\x9a\xa7\x7e\xaa\x6d\x64\x8a\x84\x2c\x6c\xd4\xbf\x7b\x97\xf9\xbd\xb2\x54\xe2\xd3\xca\xba\x55\x75\x40\x64\x01\x39\x3d\x44\x82\xaa\x6c\xb8\xb9\x8a\xce\xee\x25\x2e\xe2\xc1\x7c\x3a\x64\x72\x53\x20\x81\xcc\x91\x17\x1a\x2d\x8c\x33\x71\xcf\x58\x88\xa9\x72\xac\xcc\x55\x00\x35\xe6\xcc\xa3\x98\xe9\x00\xbf\x5b\x97\xd1\xad\xb9\x9e\xbf\x1b\xd5\xe0\xcd\x29\x25\x9e\xd0\x85\xd0\x55\x92\xaa\x40\x6b\xba\x65\x6f\xb8\x1a\xac\x30\xa3\xac\x00\x60\x35\x09\xec\x34\xd5\x98\x1c\x4a\x43\x17\x44\x74\xd9\x6e\x03\x96\x29\x79\xd6\x3f\x88\x64\x4a\x04\x75\x13\x34\xab\x4a\x88\xde\xac\xa9\x79\x9e\xe3\xf6\xc6\x08\xe7\x69\xc0\xfe\x11\x7c\x4b\x77\x5c\x59\xe6\x66\xba\x41\xaf\x09\xa9\x54\xfb\xb7\xc4\xfb\x5d\xc4\x76\x5e\x30\xef\x03\xc8\x99\x8b\x9b\x2a\xe6\x17\x5f\xab\x98\x8b\x33\x8c\x56\x24\xc7\xc5\x76\xf5\xdc\x8c\xac\x59\x84\x4b\xee\x6b\xd4\x9e\x51\x75\xeb\x9c\x08\xf0\xc0\x7c\x43\x54\x26\xc1\xbc\x47\x18\xd8\x71\xf1\x8f\xeb\xb3\x52\xed\x44\x70\x44\x2e\x41\xcf\xe8\xdd\x7c\xe5\x52\x86\xb0\x0a\x10\x1b\x0d\x80\xa7\x96\x56\x72\x71\x33\x03\x40\x57\xa2\x58\x10\xab\xd6\x0d\x36\x25\x71\x10\xe6\xa6\xac\x38\x59\xc3\x87\x62\x7e\xa8\x34\xfd\xa5\xb1\x5a\xd4\xde\xd6\xa8\x37\x3a\x79\x51\xdd\x67\xdc\xd0\xeb\xa6\xbd\x52\xa3\xaf\x79\x96\x2e\x0e\xf5\x71\xc3\x4a\xcc\x67\xad\xdd\x4d\x32\x5d\x24\x04\xb1\xa9\xa1\xb6\x14\x99\x41\xa1\x95\x3d\x6d\x3c\x11\x6e\xa1\xc0\xfe\xaa\xb0\x34\x7a\x49\x77\x12\xdf\x74\xd7\xd3\xb8\x19\x86\x27\xd9\x4a\xa4\xec\xbf\x60\xfa\xb4\x30\xee\x81\xde\x67\xd6\x58\x65\x70\xa9\xf5\x0e\xa5\x7c\x03\xbd\xd1\xd8\xde\x61\xac\xff\x73\x32\xdd\x9f\xdf\x94\x43\x3c\xff\x5a\x0e\xf1\x0a\x9d\x0b\xda\x76\x7f\x7e\x73\xe6\x80\x99\xb9\xc8\x72\x31\xac\x79\xcc\x53\x5a\xec\xed\xf1\x3c\xa5\xe8\x2c\x52\x8a\xe7\x48\x5c\xf5\x85\x1c\xc2\xea\x64\xc9\xd8\xd9\x46\x40\xb1\x0f\xb9\x6f\x8e\xbf\xc5\x49\x89\x4a\x0b\x15\x43\x53\xb8\x91\xaa\x41\x52\x16\x0d\x55\x1c\x57\x74\xd9\x4a\xb5\x82\x72\x64\x61\xcf\x40\x54\xd5\xef\x20\x7b\x92\x21\x5a\x6c\x7b\x7b\x2e\x93\xa7\xd1\x55\x21\xb0\xd7\x3c\xc4\x00\x0c\xd8\x5e\x98\x8d\x16\xbb\xa7\x7b\x52\x54\x76\x23\xc3\x9b\xa7\x55\xab\xce\x1c\xa2\xe4\x5e\x1c\xd7\x17\x16\xe5\x55\x37\x12\xbf\x98\x38\xd1\x37\x76\x99\x4b\x8c\x82\x04\xac\x39\x57\xf1\x32\x2a\xdc\xbe\x31\x6d\x16\xc3\xe0\x64\x89\x96\x82\xe3\x22\x59\xaf\x25\xeb\x6e\x42\x03\x33\xd1\x90\x7c\x21\x1a\x78\xa4\x9b\x8d\x86\x46\x13\x9f\xf7\x47\x6e\x98\x7e\xb5\x46\x83\x89\x6f\xd6\x42\xbc\x6e\xc8\x9f\xd1\xd8\x4e\x75\x0e\xaa\x6d\x89\x3c\x7a\x76\xdd\xed\x10\xa4\xcb\x1b\x01\xf0\x8f\x0a\x5e\x9a\x0f\x7b\x06\x6e\x32\x29\x2f\x48\x14\xdb\x63\x6b\xb0\x89\x71\x0b\x91\x94\x4a\xd5\xb1\x5b\xe3\xf7\x49\x30\x75\x8c\x74\x32\x18\xa6\x8e\x66\xb1\x7e\x61\x6d\x69\x99\xa4\xfd\x7b\xb5\x77\x7d\x49\x9b\x67\x9d\x89\x8b\x0c\xbf\x9d\xda\x7d\xe5\x14\x9f\x20\x4b\x4b\xc5\x45\x9e\xd7\xaf\xe6\xc8\x44\x5b\xfa\x85\x64\x4c\x57\x9a\xdb\x48\xfb\x1b\x06\xf0\x63\x56\x0b\xf5\x21\x6e\xf6\xf5\xa1\x3e\xcf\x6f\xa2\x94\xd4\xce\xdf\x69\x56\x61\x9c\x62\xb1\x1c\x5f\xea\xbc\x1d\xe7\x31\xa8\x9b\x88\xf3\x36\xe4\x84\x30\x1d\x05\x99\x38\x55\xa9\x84\xcb\x06\xa8\x9a\x8e\xaa\x5c\x07\x56\x4a\x3a\x42\x33\x4c\x1b\x7c\x28\x3c\x32\x5c\x1e\xf7\xb4\x32\x74\x49\x48\x3d\xc3\x97\x62\x78\xf0\x39\x3a\xa3\x9c\x84\x70\xf0\x9a\x8b\xff\x6f\xea\xc7\xe5\x5f\xdf\xbb\xff\x1b\x77\x1d\xfc\x92\x04\xe6\x50\x07\xbf\x24\x98\x66\x13\x09\xe8\x97\x6b\x6d\xf2\x5f\x36\xda\xe4\xbf\x6c\xb5\xc9\x7f\xd9\x6c\x93\x13\xc0\x7f\xa2\xbe\xf2\x80\x79\xef\x5c\xef\xc1\x4d\xf5\x15\x28\x88\xfa\x22\x9e\x17\xda\xc4\x20\x1d\x3c\xaf\x87\xfb\x82\xfc\xf6\x6c\xaa\xf3\x95\x3a\x0e\x2b\xb4\xf9\x63\xb5\xb2\xf5\x18\x0a\xea\x96\xf2\x54\x9c\x55\x2b\x9c\xcd\x9a\x6a\x3d\x93\x86\x81\xaa\x9d\xd3\x61\xbc\xdd\x5e\x0d\xfa\xcd\xd6\x45\xbd\x11\x91\x9a\xb6\xa8\x35\xb2\x89\xc5\xd7\x9b\x10\x16\x52\xb5\x81\x55\x02\xf5\xea\xde\xec\xba\xa3\xd4\x38\x9e\x07\x8a\xc3\x17\x5c\xda\x54\xa8\x00\x75\x64\x47\x3d\x93\x3f\x4b\xbb\xc7\xbe\xbd\xc9\xaa\xb0\xc5\x83\xbe\xc5\x63\x7e\xee\x90\xaf\xfc\xa6\xa9\x3c\xb9\xf8\x33\xef\x5f\x2a\xe8\xfe\x25\x1b\x55\x51\x52\x20\xa3\x98\x36\x38\xff\x1b\xd1\xa5\xb2\x03\x36\xe8\x9e\x88\xc3\x0d\x59\x8d\xcf\x09\x28\x43\xfd\xba\xe1\xce\x08\x6b\xb8\xb3\x06\x73\xa1\x55\x33\x0a\x1a\xc1\xce\xea\x7c\x15\xba\x77\xcb\x32\xd1\x29\x90\x29\xc1\xa9\x3d\xfc\x7c\x75\x5c\x64\xe1\xff\xdf\x46\xbf\xf9\x02\x5e\x6b\xf0\xb8\x7b\xb8\x6d\xf0\x9b\xf6\x4c\x08\x2a\x5a\x43\x9b\x34\xb2\x7a\x33\x5f\xb1\x37\xd1\xdc\x0d\xab\x4d\xd1\x86\xb8\xf4\x0f\x95\xb8\xf4\x5a\xa5\x5a\x5c\xfa\xff\xa9\xd7\x64\x0d\x75\xbf\xc2\xd7\x51\x69\xe1\x4b\x5d\x1a\xdc\xd8\xdf\x96\x3d\x12\x0f\x9a\x79\x99\x72\x65\x34\xf6\xb6\xdd\x95\x81\x7d\xd8\xe4\x69\xe5\xf0\x6b\xf0\x6b\x3c\xb8\x99\xaa\xf6\xf7\xfd\x1a\xda\x73\x21\x1a\xe1\x59\x9a\x31\xaf\xf3\xf5\x4e\x0b\x0e\x28\x26\xed\x29\x82\x33\xae\x68\xfc\xda\x90\x97\x47\xec\x50\xfc\x95\x04\xe6\xb0\x06\x7f\x25\x98\x7e\x1a\xd5\x8c\xbf\xf8\x0e\xc5\x5f\x6a\x87\xe2\x2f\x63\x6b\x20\x90\x0f\xd6\x5b\xa2\x79\xf9\x02\x1f\xf0\xeb\x35\xba\xca\x5f\x1b\x75\x95\xbf\xb6\xea\x2a\x7f\x25\x32\x93\x75\xf0\x44\x3c\x21\x96\x82\x7b\x7c\xc8\x45\x06\xaa\xca\x07\x06\xa8\x70\xbd\x0f\x37\xd5\x55\x3e\x7c\x85\xae\xf2\xe1\x6f\x7a\x6c\x2d\x95\xe5\x83\xe1\x60\xc2\xf9\x7b\xc3\x07\x03\x04\x66\x76\x33\x60\x99\x74\x35\xd1\x79\x48\x8e\x85\x9f\x19\x7f\x22\x2c\x3c\x14\x29\x1a\x10\x0b\x8f\x18\x1e\x0e\x7c\xf4\x95\x70\x7e\xe4\x3a\x86\xdb\x69\x69\x30\x1f\xdd\x58\xb3\xb2\x32\x3c\x37\xa5\x02\xb2\x9a\x6a\x0c\x21\xe1\x09\xd1\xb8\x7a\x66\x1f\xd9\x94\xbe\x0a\xab\x93\x71\x31\xa9\xf1\x92\x91\x5e\x6a\x3c\x6b\x42\x82\x37\x56\xda\x7d\xd7\x74\x2c\x75\xda\xbd\x69\x09\x53\x63\xd2\x5f\x55\xf5\x56\x0f\x0c\x7f\x93\xa1\x6e\x68\x77\x0a\x9f\x31\x4c\x80\x2e\x7e\x06\x9f\x85\x26\x27\x72\xa1\xdb\xa0\xd5\xbd\xda\x55\xb4\xe8\x1b\xc3\xf9\x6d\xe1\xdf\x1a\x39\x9b\x57\xc9\x59\x02\x23\xc0\x2b\x1f\x77\x5a\xdf\x76\x8a\xce\xb7\x2d\xcc\xe3\xfc\x6d\x47\xce\xac\x7d\x4a\xbf\x32\xae\x5c\x64\x99\x68\xb6\x85\x41\x9b\x50\x9c\x4e\xe2\xd9\x97\x63\x49\xaa\xe3\x68\xd0\x85\x37\xcc\x6f\x13\x97\x34\xa1\x52\x9a\xf2\x26\xb0\xd8\x66\xb0\x58\x15\xac\xaf\x12\x6f\x8f\x6e\x24\x70\xea\xf2\xed\xd4\x69\xa0\xd9\xea\xdd\x17\xe6\x11\x25\x99\xa9\xbb\x41\x1e\x35\xc2\x70\xbd\x88\xfd\x07\x40\x60\xcd\x10\xfc\x63\x12\xd1\x9c\xeb\xcd\xc2\x51\xcd\xe8\x4d\x05\x23\xdf\x96\xcc\x02\x13\xec\x41\x96\x91\x9c\xcb\x32\x29\xe7\xe0\x97\xda\x77\x57\x6f\x2b\xfb\xee\xf0\x9e\x2b\x8b\x72\xbf\x5c\xbd\x21\x19\xf8\xd0\x94\x81\xf2\x8b\xbd\xef\x2e\xdf\x92\x34\x35\x77\xdd\xad\x2f\x56\x6b\xf2\x85\x55\xa2\xbe\x67\x0f\x5f\x2b\x91\x04\xf0\xa6\x16\x25\xa0\xde\x55\xa2\x04\xe0\xfd\x35\x12\x1b\x4a\x6c\x90\xd8\xf4\x65\xa3\xc4\x2e\x9c\xdf\x19\xe6\xdc\xf8\xfd\x86\x92\xc8\x76\x60\xb6\x78\xea\xed\xf1\xa4\xe5\xcb\x9f\x3b\xad\x0e\x9f\x63\x4a\xa0\xdd\x69\x75\xbb\x5d\xf9\x86\x25\xb3\x8e\x23\x3f\xb2\xe5\xb0\x3f\x6a\x61\xd6\x6e\x5d\x81\x2d\xfd\x56\x0b\x85\x1a\xa6\x33\xfd\x7d\xbb\x10\x6a\x88\x07\x34\xfb\x55\x7b\x22\xdf\x19\x8d\xb3\x4a\xab\x8d\xb9\x45\x38\xd5\x3b\xc5\x9e\xd1\x9c\xbb\xaf\x5b\x51\xa1\x3a\xc3\xa0\xd7\x6e\xb3\xbb\x0a\x1b\xfc\xf6\x3a\x4a\xd4\x34\x8f\x53\x60\x08\xb8\x18\xad\xfe\x9a\xdc\xaf\x56\x08\x92\x76\x9f\x8a\x18\xef\xa2\xea\x78\x65\x15\xc7\xab\x57\x0c\xf1\xbc\x08\x4f\x95\xde\x03\xeb\xcf\x97\x69\xd3\xb1\x08\x17\xac\x0a\xfb\xc2\xf9\x7f\xc2\x6f\x04\xa8\xbc\xa5\xc1\xb9\x55\x90\x29\x50\xf8\xf9\xbc\x01\x43\x16\x82\x28\x0c\xe0\xbf\x75\x3b\x80\x88\x9e\x64\x73\xcc\x44\x1e\x86\x2d\x10\xe2\x12\x8d\x38\x15\xd6\x21\x9c\x73\x7b\xfd\x0a\x10\x71\x98\x17\x8f\x1b\x00\x31\x69\x40\x00\x4a\xfa\xcb\xef\x37\xe1\xc1\x95\x00\x70\x1e\x30\xaa\x5c\x8e\x08\x2c\x46\x4a\x5b\x44\x95\x7c\x27\x0e\xa4\xf1\x67\x4a\x20\x98\xa8\xec\x86\x14\xa9\x8e\x31\xfe\xc4\xd7\xaa\x99\x0c\x07\x51\x07\xef\x36\xcd\xfc\xcc\xc8\x69\xd8\x08\xe8\xb6\x6c\x1b\x5f\x0b\xe5\xb6\x00\xb4\x30\x88\x54\x48\x8a\x84\xd1\x4b\x87\x3a\x0a\x0d\x46\x87\xf7\xa7\x57\x11\xcb\x3e\xae\xc2\xb8\x59\xcd\xb4\x33\xfa\x9b\xd0\xf1\x1b\x70\xe8\xa7\x94\x27\x98\x5b\x9f\xde\xc2\x0f\xf9\x4e\xd0\x50\x21\x16\xee\x6f\x2a\xf0\x83\x8b\x8b\x08\x55\xe8\x77\xc4\xb8\xde\x7d\x25\xe3\x62\x4b\x16\x16\x82\x73\x89\xdf\x8a\x13\x91\x13\x19\xd8\x90\x78\xa6\xed\xc9\xd6\x4e\x11\x2d\x58\x4e\xac\xe9\xdd\x57\xb2\x26\xb5\x05\xfb\xee\x5a\x2e\x24\xda\xf8\xc6\xcc\xe8\x4f\x31\x8e\xef\xae\x63\x28\x37\x8a\x71\x94\xd7\x06\x18\x8d\xf3\x38\xc7\x3d\x1e\xf5\x58\xed\xa8\x21\x95\x98\x19\xb3\x53\x1d\xd0\xc6\xa5\x5a\x1d\xcf\xa8\xe7\xe3\x6a\x7f\xf7\x05\xab\xbd\xd6\x84\x1a\x6a\xbd\xa9\xeb\xd7\x3e\xf9\x2f\x15\xae\x12\x79\xe0\xc4\xec\x22\x69\x58\xd0\x89\x4e\x2e\x9b\x6c\xe8\x73\xcb\x32\xde\x9a\xe5\x49\xee\x5d\xdc\xe5\x57\x12\x8d\x64\x5a\xa7\x44\xc0\xe3\xfa\x62\xef\xe2\xdd\x57\x2c\xc6\x77\x6c\x54\xc1\x9f\x6a\x15\xd7\x98\x58\x5e\x60\x16\xcd\xbb\x32\xb5\x78\x70\xe8\x7d\x83\x67\x34\xaf\x44\x06\x6b\xf3\xf2\x9a\xdc\x38\xca\xee\x0a\x0b\x4b\xdf\x66\xae\x3e\x95\x65\x25\xc3\x9c\x4e\x59\xd7\xec\x51\xc2\x9b\x24\xe8\xfe\x08\xdc\xaf\x5e\x7b\x66\xa2\xe8\x86\xbb\x73\xb0\xc7\xa9\xc8\xc1\x82\x85\x7f\x7d\xb5\xe9\x82\x1d\x33\x3b\x5c\x13\xaa\xda\xed\xc6\x7b\x57\xb0\xc9\x11\xff\x83\x07\x09\x48\xe7\xe6\x0f\xbc\xbb\xe7\xcf\xfe\x07\x3a\x7c\xfe\x6c\x24\x7f\x34\x74\x2a\x93\x72\x6f\x40\xc7\x4a\xa7\xf6\xc3\xd2\x4f\xc3\x65\x43\xc1\x0f\x62\xf6\xcc\x0b\xff\xa8\x38\x4f\xe9\x78\xdd\x44\x5f\x55\x23\x2b\x6e\x32\x91\x3a\x50\xa7\x01\xa0\x0b\xb6\x09\x20\xe5\x7d\x69\x1a\x06\x73\x4e\xf8\xe4\x8f\x2a\xc4\xe5\x2b\x92\x68\xae\xf9\xe0\x66\x35\x37\xa3\x39\x36\xa8\xae\xb9\xd4\xa5\xd9\xbe\x49\xc7\xd0\xc7\x89\xfd\x4d\x8f\xd9\x57\xb4\x53\x88\xbc\x61\x28\xd8\xc2\xe9\x59\x43\x07\xcf\x6f\x30\x06\x8c\x8c\x6e\xa8\x1a\xdf\x64\xf8\x24\x4f\xeb\x95\xc5\xd5\x03\x60\x42\xa0\x40\xd4\xae\xa9\xea\x35\x1e\x8d\x61\x0f\x1d\xe6\x17\x5a\xbc\x5a\x29\x1b\x4f\x2d\x47\x17\x90\xc9\x92\x65\x6e\xf7\x43\x1a\x25\x4e\xcb\xdb\x21\xe3\xa0\xd5\x01\x09\x3a\x4d\x93\x69\x68\x0d\xea\xfa\xdd\xb3\xd7\x62\x51\x1c\x9a\x0e\x79\x3c\xfb\x15\x02\x87\xf4\x9b\x96\x27\x57\x2c\x8d\x4c\x78\xf2\x61\x63\x69\x7b\xd3\xc3\xc8\xa4\xc5\xef\xe0\x42\xcf\x38\x3f\x0a\xb7\x89\x63\x18\x0e\x85\x43\x72\xa4\xe3\x1e\x52\x05\xab\xf5\xd5\x48\xb7\xbf\x5d\xb3\x1a\xe9\x00\xaa\xb1\x0b\x43\x78\x12\xe7\x52\xf5\x45\x4e\x89\xba\xc8\xc9\x03\xc9\xc6\x37\x1b\x9b\x27\x55\xa2\xf3\xdc\x38\x26\xca\x37\x5b\xe7\xa0\x01\x58\x75\xf4\x55\x6f\x04\x1c\x7e\xa7\x58\x45\xcb\x8b\x95\x8d\x30\x4f\x9b\x9f\xf0\xfa\xf4\xbd\xd2\x31\x8d\xf4\xef\x0d\x13\xc6\x37\x8e\xbc\x6c\x82\x43\x14\x99\x17\xe4\x48\x93\xd9\x13\xd0\x3c\x9a\xfa\x6d\xe2\xe8\x46\xf4\x95\x35\x1a\x68\x89\xef\x86\x35\xb7\x61\x4d\x9d\x57\x19\x03\xde\x04\x49\xb7\xcc\x81\x38\x46\x6a\x43\xb2\xb7\x28\xad\x52\x5b\xdf\x12\x5b\x8c\x5a\xb0\x9a\xfc\x96\xd7\x12\x5e\x9b\x56\xcb\xbb\x11\x4d\xb8\x57\xc9\x08\xa7\xdc\x67\x9d\x00\x93\x05\xd0\xd1\xb3\x5d\x3a\xbc\xae\x1a\x87\x89\x31\x6e\xfe\x00\x13\x9d\xe7\x77\xc5\x84\xea\x37\xa0\xe2\x23\xa4\xe2\x85\xc9\xef\x9b\x88\xc8\x4c\x00\x0b\xe5\x81\xd9\xaf\xa6\xac\x46\x43\x75\xc2\x87\x69\x95\x63\xac\x06\x08\xde\x3d\x18\xe1\x75\x68\x7e\xa6\x43\xfa\x1a\x24\x14\xa5\x64\x88\xf0\xb6\xdc\x5d\xb4\xab\x00\xf3\x78\x3d\x1c\x11\x0d\x66\x4d\xe0\x05\x78\x16\x59\x0e\xd4\xcb\xe8\xe4\xb4\xd8\x46\xdd\xd6\xfd\xb9\x8a\x4c\x14\x95\x77\x79\x33\x62\x37\x31\xb3\x76\x2c\x45\xe9\x06\xac\x4a\x3c\x19\x39\x7b\xa1\x3c\xe9\xff\xdb\x11\x7b\x59\x5b\x9d\xc8\xa2\x1a\xeb\x70\xa7\x2f\xdf\xb4\xfe\x55\x1d\xc5\xc2\x4d\xca\x26\x76\x27\x3b\xb0\xb6\x37\x49\x84\xdc\x84\x2a\x8e\x91\x2a\x8e\x57\x05\x2e\xb9\x4d\xc5\x79\x90\xa0\x38\x0a\x18\xe5\x87\xe8\x94\x6f\x28\xab\x17\x81\x92\x30\x96\xbc\xf1\x77\x1b\x38\xb3\x1a\x73\x8f\x72\x42\x62\x0e\x8a\x66\x3c\xa6\x4e\x31\xb2\x16\xbe\x88\xbf\xa0\x44\x8a\x42\x4c\x52\xf5\x9f\x37\x70\x8d\x85\x95\xcb\x8a\xeb\xe9\x4d\xf8\x34\x6c\x5c\x4f\x66\x15\xad\xcb\x37\x2c\x42\xd7\x26\x88\x7b\x63\xcc\x23\x31\x67\xfa\xad\xf4\xdd\x5a\xc2\xf5\x4f\xe6\x56\x54\x10\xe5\xcb\xb2\xc2\xc7\x9b\xac\x3c\x9d\xc2\x94\x49\xa9\xf0\x2c\xdd\x80\x32\xc1\xe3\x09\x4d\x9a\x8e\x24\x83\xad\x2d\x1d\x9b\xbb\x36\xad\x1d\x62\xb1\xa2\x38\x36\x94\x6d\xa6\x19\x2a\x89\x73\x32\x8f\xc3\xe2\xe9\x75\x5c\xe7\xc2\xe6\x3a\x58\xa7\x60\xc9\x36\x6a\xff\xa4\x6a\x08\x51\x67\xe0\x6d\x83\x92\xb8\x54\x4a\xa2\x75\xf5\x67\x03\xc6\x00\x74\x5b\x77\x56\xca\x03\x5d\x8f\x2e\x8f\x87\x32\xde\xd4\xe3\xa4\xd2\x98\x79\xfc\x8f\x80\x8c\x02\xca\x19\x39\xd8\xc5\xd3\x7f\x4d\x97\x01\xe0\x1d\x01\x3a\xbf\x2a\x32\x7d\xca\x99\x2a\x32\xa7\xa6\x78\xc4\xc2\x9f\x63\x73\x66\x6a\x23\x95\x2a\x1f\x58\xe2\x49\x96\xae\x96\x9b\x28\xff\xc4\xa2\xfc\xd3\x70\xb3\xd6\xc4\xfd\x94\xd0\xc5\x2e\x76\x44\x65\x1f\x37\x4e\x83\x2c\x2d\xf2\x8a\xca\xf2\x51\xfe\x6a\x75\x5c\xbd\x35\x55\xc5\x4c\x35\x9a\x58\x52\x93\x1b\x41\x25\x24\x51\x83\xf7\x35\xa8\x6f\x95\x98\x15\xde\xe3\x12\xa9\xb3\xb9\xcf\xae\x84\x48\x4e\x3d\xdf\x9c\xbe\x89\x99\xf8\x4b\x6d\x95\xae\xbd\x78\x0b\x97\x6c\x52\x48\x60\x81\x38\x24\x75\x3f\x35\x41\xf7\xaa\xd0\x9c\x06\x8a\x6c\x9a\x3e\x59\x8c\xfb\x9d\x16\x51\xe3\x84\xa8\xb6\x46\x74\xf1\xa1\x9f\x24\xbc\xec\xb5\x8d\x62\x79\x86\xe5\xa9\xf5\x8c\x5d\x27\x06\x50\x06\xe4\x67\xd1\x72\x23\x55\xf0\x62\xc6\xcd\x96\x24\x90\xb0\x4a\x85\xeb\xd4\xd6\xf4\x06\x34\x62\x55\x8c\x2b\x50\x6f\x44\x73\x7f\x9c\x46\xf1\x35\x42\xf7\xb8\x2e\x74\xa1\xe2\x9b\xa4\x88\xaa\xf7\x37\x58\x23\x90\x8d\x57\xa4\xef\x26\x5c\x56\x25\xb0\x08\x13\x2a\xc2\x33\x76\x0d\x96\xc4\x45\xa5\x06\x9e\xb0\xd2\x57\xe2\x09\xab\x56\xf1\x84\xef\x6e\x80\xa7\x23\x9b\xff\x62\xad\xeb\x90\xa4\x5a\x36\x90\x24\x0d\xd7\xcd\x4b\xc4\x5e\x4e\x18\x75\x7d\x3f\x9d\x35\xe9\x59\x42\x4f\xe1\x77\x12\x3b\xc6\x53\x80\x57\x62\xe2\x5a\xc6\x8b\x94\x49\xbc\x62\x64\x82\xb1\x65\x19\x66\xe3\x73\x1e\xff\x01\xbf\xf0\x42\xbc\x50\x44\x23\x63\x50\x9a\xf0\xdd\xe0\x3b\xe1\x46\x93\x2f\x4d\x43\x37\x28\x12\x7c\x2d\x6f\xe6\xa3\xc2\x37\xbf\x90\x0f\x8a\x4f\x4f\xc1\x94\xc5\x7a\x42\xfa\x99\x19\x8f\xf1\xca\x8e\xe6\xbb\x3a\xc2\xcc\x6b\x71\x95\xb9\x55\xbb\x9e\x1a\x63\x01\xe6\xdd\x24\x7d\x42\xdf\xff\x08\xb3\x04\x7a\x13\xca\xc8\x00\x9b\xac\x44\x39\x88\xab\x3e\xe8\x66\x12\xd6\xa5\xdc\x29\x78\xa2\x73\xaf\x4f\xde\x7c\xb9\x49\xd3\x3a\xba\xc8\xc2\x25\x87\xa6\xa5\x02\x0c\x30\x2c\x23\x8d\x59\xbb\x2d\x7e\x74\x2f\xa0\x3b\xfb\xc9\x69\xc9\x0b\x82\x84\x92\xbf\x03\x73\xb3\x73\xcc\x58\xb2\x33\x63\xcb\x8c\x41\xef\x6c\xe6\xed\xac\x30\x9f\x8c\x2c\x88\x3a\xe0\x4e\x9a\xe9\x17\xa4\xae\x01\xe1\xee\xbc\x06\x14\xee\x5c\xf0\x31\xed\x5c\x44\x71\x0c\x2d\x4d\x41\x4d\xdc\x09\x77\x72\xa0\xb0\xa4\xd8\x61\x38\xa6\x9d\x08\x8c\x8b\x9d\xf9\x0a\x80\x64\x3b\x48\xe3\x80\x9a\x2e\x7a\x2f\x8c\xbb\xfc\x28\xb7\xb8\xba\xe6\x84\xae\x37\xf9\x86\x39\xa7\xde\xd5\x3c\x8e\x9a\x5c\x5d\x72\x05\xcc\x0b\x49\x55\xa4\x20\x81\xf6\xd3\x64\xf3\x6e\x33\x9b\x31\xfd\xca\xb8\x37\xd1\x0a\x56\xbd\x8d\xeb\xed\x57\xa8\x23\xac\x57\x10\x54\xcf\xe7\x1b\xd9\x87\x2c\xbb\xd5\xc3\x11\x73\x20\xae\x69\x46\x80\xba\xbd\x29\x10\x88\x87\x55\x7f\xc9\x16\x67\x7a\x23\xa7\xb2\x7c\xaf\x8d\xbe\x81\x71\xea\x45\x13\x79\x9d\x83\x5b\x39\x4a\xc9\xa1\xf8\xcd\x32\x76\x37\x04\x71\x34\x76\x8f\x04\x50\x85\x02\xac\xd6\x66\x0f\x05\xef\x9f\x6a\x28\x3e\x93\x67\xc1\xa9\xc1\x67\xf2\x6c\xbc\xe0\x7c\x26\x57\x7c\x46\xa6\xd1\xca\x6d\x46\xc3\x17\x98\x7c\x6b\x71\x9a\x46\x02\xa9\xdc\x2d\xcc\xdc\x4e\xcb\x47\x3a\x4f\xc8\xf7\x05\xf4\x3c\xc3\x5d\x80\x9b\xba\x9e\xfb\xee\x57\xf8\x8f\xfa\x72\x25\x10\xc7\xfe\xe2\xb5\x30\xc2\xa5\x40\xfb\x40\x82\xd5\x58\x24\x68\x04\xb4\x58\x86\x06\xd1\x7c\xed\x98\x35\x9d\xae\xdf\xeb\xe3\x7e\x9d\xb1\x25\xb5\x91\xa6\xeb\x0b\xcb\xdc\x92\xfe\x02\xcb\xbe\xff\x35\x96\x3d\xaf\xb4\x6c\xa8\xc5\x91\x56\x75\x8e\xd0\x86\xbd\x71\x73\x79\xc9\xbc\x1e\x3f\x34\x90\x94\xe5\x01\x4f\x4e\xb9\xcb\x2a\xa1\xe3\x76\x2c\xc2\xc0\xf0\x79\x48\xb5\xa2\xa8\x39\x5b\xfb\x74\xdb\x7a\xe6\x67\x5d\xee\xb2\x75\x8c\x7b\xa9\xbd\x03\xc9\x41\x79\x56\xa6\x0e\x73\xe5\xf4\x3f\x91\x18\xdf\x4c\x02\xd6\x14\x9a\x1c\xc5\xa4\x08\xe3\xc6\x77\x98\xca\xe4\x1a\xeb\x91\xdf\x1f\xf1\xa5\x86\x20\xe1\x7e\xb3\x6d\x57\xcb\xb6\x25\x31\xc8\x6f\xd5\x2e\xcb\xba\x03\xa3\xdd\x2e\x86\xda\x9b\xc1\xfc\x6b\xec\x43\x8a\xf7\xb3\xcc\xc3\x4d\xc6\x96\x01\x4b\x41\x61\x18\x4e\x83\xf7\xa4\x06\x60\xa1\xb7\x48\x61\x6d\xc9\xb2\x9a\xbc\xc9\x31\x0e\xeb\x7c\x99\xe6\x8d\x9a\xa7\xc4\xd9\x7d\xd3\x55\x44\x35\x62\x16\x9e\x5b\x8b\x82\x7b\x39\x28\xc5\xdb\xa4\x81\x62\x5c\xba\x2d\x5b\xed\x5b\xd1\xdc\xd3\xc5\xb3\x1e\x1d\x3c\x67\x5d\x31\x73\x8e\x71\xa7\x15\x13\x28\x75\x12\x71\xcc\x95\xfe\x7c\xa7\x8e\x47\x78\x12\xbc\xe4\x1a\x4b\x0b\xa9\x63\xaf\xff\x95\x56\x00\x11\xc9\x67\x5b\x17\xb8\x76\xb0\xd5\xc5\xf4\x5c\x6a\xfa\x09\xc7\x21\xb4\x87\xb1\x67\x0d\x4c\xce\x6c\x46\x21\x02\x78\x23\x17\x99\xd5\xf6\xb8\xfe\xbd\x76\xbd\x99\x71\x48\xfe\x84\x4b\x19\xf3\x95\x08\x70\x06\x49\x70\x5e\xd1\x14\x37\x06\x3e\x20\xfb\xbc\x76\xd7\x44\x9e\xf3\xda\x6e\x25\x1b\x17\x9d\x01\xa8\xe7\x95\x70\xe7\x50\x5f\x5a\x84\x00\x3e\xf6\x0c\xa1\x49\xca\xd8\x0b\x73\x28\xf4\xe6\x81\xd9\x08\xbd\xf9\xad\x56\xeb\xf7\x5a\xad\x77\x56\x2d\xe2\x82\xab\x2c\xb8\x92\xfb\x61\xfe\xdc\xc3\x31\xbc\xf6\xee\xa7\x71\xcc\x68\x1c\xfe\x5b\x0f\x5d\x51\x1f\x0a\xcf\xd8\xfe\xbc\x60\x1e\xed\xcb\xc5\xcc\xe3\x7b\x7b\xcf\xe1\x07\xa0\xf4\x01\xf3\x8c\xed\xce\x0f\xcc\x7b\x09\x3a\x69\x36\xf3\x1f\xc1\x2f\x0c\xb1\xf3\x7f\xc7\x57\x18\xb1\xe2\xbf\x63\x5e\x94\xfb\xdf\x90\x13\xea\xd7\x57\xfe\x2f\x6a\x43\x76\x95\xa1\xf2\x74\xb5\x9e\x78\xdf\xfb\xe3\xaa\xbf\xcd\xda\x88\xb6\xee\xe6\x11\x3f\x77\x32\x9d\x2a\x10\x16\xbb\xe6\xba\xc8\x66\xd0\x47\x8e\x92\x91\x9c\x90\x43\x56\x96\xbb\x20\x30\xf0\xcb\xcb\x76\x3b\x93\xf2\x42\xa4\x85\x01\x66\xb7\x9b\xf1\xb8\x5f\xf8\x2a\x1d\x48\x7b\xea\x56\xd7\xde\x5a\x75\x19\x49\xe8\x74\x4a\x39\xb9\x40\x31\x23\x27\x08\x10\x3c\xef\x3f\x8a\xf6\xf6\xfc\x4e\x27\xba\x9b\xd1\x6d\x98\x20\x32\xc6\xfc\xf6\x5f\x9d\xbb\x77\xa0\x3a\x51\x6d\xa7\x46\xce\x1c\x46\x03\x92\xae\x59\x8a\x75\x31\xb2\xd8\x25\x74\xcb\xaf\x3a\xcf\xd6\xe9\x64\x77\x23\x7e\xef\x26\x26\x93\x31\x6a\x66\x0d\xdd\x84\x9a\xaa\x9b\x3c\x4e\x80\x0b\xa3\x70\x6e\x14\xe6\x1a\x97\x51\x14\x56\x0d\x6e\xc3\xf0\x6d\x1d\xdc\x2a\x6d\xe9\x8a\x2b\xcb\xcd\x04\x06\x5f\x86\x96\xec\x3d\x92\x5b\xaa\xd0\xb4\x1a\xe6\xc2\x63\xc6\xf4\xb8\x92\xbb\x59\xbb\xcd\x34\x0b\xa7\x86\xee\x51\x4a\xec\xe1\x9e\x91\x0c\x2c\xd1\x6d\xc6\xb5\xb0\x39\x75\xec\x6f\x6f\xef\x4b\x1b\x5b\x5a\x0c\x23\xc3\x3a\x19\xda\x67\x51\xe8\x31\xf5\x13\x93\xb3\xf0\x56\xf7\x44\xeb\xba\x81\x79\x95\x5e\xa2\x80\x6e\xf4\x35\x1a\x0a\x03\xdd\x94\x97\x07\xa9\x24\xa7\x95\x4a\xf0\x3a\x40\x52\xca\x85\x2f\x74\x1a\x64\x4e\x8a\xe4\x14\xc2\x7f\x74\x88\x4e\xa5\x42\x8e\x86\xc1\x0a\xd3\x99\x7f\xe7\x24\xf0\x6d\xd4\xf7\x51\x0a\x18\x9e\xc1\x46\x08\x8d\xfb\x2e\x77\xde\xe2\x3d\xcd\xfa\xd3\xcc\x74\xfb\xdb\x9f\xce\x0d\xba\x78\xff\xbe\xd5\xf9\xc6\xfe\xbc\xd8\xba\x4c\x58\xc7\x49\x28\xa2\xca\xb5\x97\x8a\xf0\xf5\xe2\x62\xa1\x3c\xa9\xb0\x06\x54\xce\xa5\x68\x5d\xa7\xe4\x13\x0d\xc4\xee\x2e\xc6\xa8\xf0\xab\x94\x0d\x0a\xd5\x65\x2f\x8d\xb1\xf4\xbf\xef\x0d\x29\xd1\xf3\x30\xf8\xa9\xdd\xee\xdf\x82\x87\xb2\xbc\x05\xda\x24\xfc\x81\x6f\xf4\xf7\xce\x0f\xe2\xc7\xf7\xfd\x3b\x3f\xd2\x0f\x28\xfd\x63\xff\xa7\x03\x10\xd0\x3f\x1e\xf4\x0e\xa8\xce\x8f\x07\xa2\x16\xfc\xb8\x25\x7f\xfc\x24\x7e\xfc\xf8\x03\x6f\xf0\xe0\xe0\x47\xde\xc0\xf7\x77\x0e\x7e\xc0\x8f\xc6\x02\x38\xda\xba\x00\x3c\x41\x2c\xe3\x09\x5f\x0a\x03\x97\x82\x54\x78\x6a\x78\xfa\xf9\x87\x97\x8e\x01\x79\x93\x40\x5f\xb6\x94\xea\xd6\x8f\xeb\xfe\x76\x8b\x71\x40\xd3\xf0\x1c\xf2\xf6\x89\x85\x5c\xf1\x04\x56\xc8\x46\x80\xfe\x40\xa5\x73\xc0\x6e\xc5\x08\xf9\x1c\xcf\xda\xa3\xfe\xb6\xa2\xdb\x9f\x56\x40\x7d\x9d\x4e\x3a\x09\x72\x45\x60\xa1\xee\xf7\x10\x71\x2d\x7b\x65\xd8\x47\x62\x2e\x6a\x76\x17\x94\xf6\x4b\xc7\xe2\x0a\x20\xd7\xf5\x02\x64\xba\xa9\x4f\x76\x53\xaa\x15\x86\x6b\xf9\x86\x6d\x5c\x18\x53\xff\xbb\x4d\xa7\xf7\xa9\x79\xf9\xc4\xc4\x79\x03\xa4\x2b\x30\x2b\x5e\xe5\xfc\xaf\x63\x85\xa6\xfd\xe9\x72\x89\x63\xbe\x53\x59\x7c\x29\xc0\xf8\x63\x2a\x92\x47\x78\xad\xa3\x23\x72\x75\x1d\x1d\xb5\xa0\x21\xeb\x3d\x3a\x96\x96\x6c\x86\x5f\x64\xe5\x10\x4f\x28\x48\x74\xa2\x89\x4a\xa7\x9c\x14\x74\x28\xfa\x2c\x7a\xe6\x2b\x4c\xf8\xfe\x54\x7b\x46\x56\x06\x2a\x99\xc3\x2b\x10\x7d\x98\x84\x8e\xbf\x16\x10\x05\xbb\xbb\x06\x8e\xfe\xc4\xa1\xdf\xa8\x29\x23\xe5\xeb\x2c\xca\xe0\x4d\x5f\x3d\x66\xe9\xf2\x3e\xfa\xac\xe0\xa5\x4a\x5e\xc1\x2d\x6b\x6a\x6d\xb7\x5f\xd9\xdf\x66\xd5\x06\xd1\x69\x2a\x5b\xf8\x14\xca\xb7\xe7\x11\xbb\x90\x25\x35\xc4\xa0\xe4\x9a\x9b\x8d\x26\x90\x2a\x25\x8f\xd9\x91\xca\x4e\x23\xdb\x83\xd5\x80\x48\xfe\xd3\xa9\x0e\xdb\xd8\x03\x37\x47\x0e\xe2\x8e\x6f\x1d\x20\xc0\x99\x1a\xbe\x89\x0b\x7a\x6d\x8c\xb8\x86\x03\x2f\xab\x8c\x9e\x61\xa3\xcc\x68\xd4\x44\x41\x1d\x2b\x54\x44\xe1\x03\xeb\x26\xb2\xae\xc6\x4c\x56\x58\x27\xd0\x74\xef\x12\x5f\x7a\xd8\xee\xa0\x50\x03\x81\x65\x5a\x54\x26\xac\xc7\x53\x5e\xcb\xe3\x68\x71\x9a\x30\x3c\xa6\x26\xab\x7c\x07\x75\x54\xe4\x86\xee\xff\x6d\x6d\x66\x14\x6a\xb9\x6e\xcc\x2f\x52\xe4\xeb\x4b\xad\x9c\xc4\xa9\x53\x9b\x95\x62\x48\xe2\x38\x09\x7a\x43\xbc\x77\xfd\x61\x82\x86\xbc\x64\x65\xf6\xdc\x62\xce\xbe\xac\x2b\xe3\xca\xd1\xf1\x34\x03\x3e\x97\xee\x45\x20\x60\x93\x51\xea\x47\x30\xd8\x55\xb0\x08\x9d\xb0\x81\xf4\x5c\x79\x85\x85\x4d\x3f\x71\x30\x1d\x4d\x45\x77\x7e\x4f\x5c\x61\x00\xac\x13\xac\x0b\xbc\x2c\x32\x44\x8e\xb4\x1a\x2e\x81\x89\xe6\x1d\xd0\x3b\x25\xd3\x3a\x45\xc4\xce\x80\xa5\xe6\xc8\x65\x4f\xef\xc6\x82\xcb\x9e\x07\xd3\xf1\xe9\xc4\x5b\x04\xe7\x32\xe1\x3a\xf3\x4e\xe0\x81\x9c\x67\xc8\x84\x82\xe0\x67\x9a\xc6\x73\xda\x09\x45\xbb\x70\x94\x0f\xcf\xb9\xf8\xf6\xf3\xbb\xe2\x97\x8b\xb6\xb1\xb8\x9c\xa2\xe7\xf1\xb2\x18\x00\xec\x89\xef\x41\xee\xed\xf2\xb7\xbc\xdb\x4b\xe8\x22\x8e\x16\x11\x71\xaa\x5d\xd1\x78\x70\x39\xa4\x8b\x0c\xa8\x99\x4e\x67\x18\x5c\xfa\xbb\x0b\xbc\x44\xc5\x95\x29\xc7\x61\x7e\x89\x16\xa8\x8d\xa3\x00\x3f\x0a\x20\x3f\xbb\xb3\xe0\x68\x20\x53\xa3\xef\x1e\x71\x0e\x1a\x04\x8f\x8c\xba\x03\xba\xa6\x1d\xdb\x58\xcf\xc7\xcb\x4e\x67\x12\xcc\x24\x9f\x9b\x6b\xba\xf9\x0d\xe9\x46\x4e\x75\x58\x84\x40\x81\x57\x6b\xfd\x19\xef\xa3\x6a\x32\xc7\xda\x6d\x7e\xe2\x6a\xc7\xaa\x6a\xb1\xf9\x77\x46\xd5\x16\xa6\x48\x07\xab\x08\x38\x2f\x2a\xae\x2f\xfd\xcd\xd5\xbe\x69\xae\xb6\x8b\xba\x83\x62\xe6\x66\x6d\xcf\xe4\xd7\xbf\x14\xa6\xf2\x58\xad\xef\x54\xbb\x0d\x44\x9c\x95\xc1\x93\x0b\xc3\x19\x38\x2a\x14\xe9\xf1\x74\x6a\x58\x1d\x2b\x07\x57\xb8\xed\xe3\xcf\x43\x07\xf9\x80\xeb\xe1\x56\x2f\x2e\xf0\x28\x5c\xa3\x94\x04\x9d\x01\x4b\xd2\x15\x14\xc5\x98\x4d\x0c\x00\x7f\x2d\x2c\x5f\x15\xb5\x06\xeb\xaa\xa6\xe7\x83\xf1\x74\x3f\x02\x26\x35\xa2\x23\x61\x84\x75\xe4\x58\xf8\xe3\x14\x5a\xd4\x71\x71\x14\x24\xaf\x9a\xff\xcb\x04\x5f\x42\x3b\xa8\x5b\x11\xd4\x7a\x81\xd7\xce\x61\xeb\x3c\xe5\x86\xcf\x78\xeb\x05\xda\xf1\xba\x49\x71\x76\xf0\xaa\xc9\x58\x40\xa4\x30\xbc\x0a\x3c\x78\x9e\xd2\x4d\x35\x42\x65\x62\xa8\x27\xa1\xb2\xd4\xa0\x19\x30\x76\x33\x03\x84\x94\x2d\x0c\xb0\xaf\x26\x21\x36\xb8\x5e\x54\x6b\xab\x62\x78\xdc\xa4\x91\xf4\x26\x00\x91\xa5\xb7\x6b\xb4\xa7\x6e\x72\x18\xa8\x60\x21\x6d\xed\x6d\x6f\xb1\xae\x62\xca\x0c\xa9\x88\x31\x06\xfc\x11\x3b\x00\x72\x15\x7a\x66\xe8\xae\xeb\x7a\x66\x7e\x6d\x1f\x34\x25\x0a\x7a\x8a\xb4\xd6\xe0\x0f\x94\x8a\xaf\xad\x47\xb6\x45\x85\x84\xa6\x0f\x43\xae\x47\x0e\xe4\xe5\xde\x48\xda\x83\x68\xc8\xef\xb2\x89\x5c\x1d\xfa\xa1\x6d\xcd\x6b\x9a\xfc\xd4\xd8\x64\x36\x8c\x36\x37\x19\x33\xae\x84\x79\x99\xac\x23\x6c\x3b\x83\x24\x01\xa2\x94\xee\x4f\x2a\x08\x81\x2e\xd9\x72\x29\xa6\x3e\x64\x94\xaf\x5d\xf8\x05\x9a\x6c\xcf\x5a\xeb\xd5\x86\x23\xd1\xf0\xde\x1e\x59\x82\x3c\xa3\xe2\x75\xcd\xce\x6f\x4c\x62\x0d\x14\x26\x77\xb0\x4c\x17\xc1\x29\x6b\xd6\xd1\x51\x50\x73\x0e\x94\x74\x82\x0e\x62\xb3\x2c\x7b\x0d\x00\xcd\x58\xc5\x0f\x1d\x04\x2f\xd1\x97\x6c\x18\x9b\x06\x26\x64\xa9\x5d\xf2\xd5\x48\x2e\x9c\xd1\x89\x21\xdf\x58\xda\x0b\x66\x87\x3c\xbe\x41\xa6\x35\x60\xa1\x8a\x67\xfc\x1c\x92\xc1\x50\xb1\xcb\x33\xd3\xe4\x4e\xd5\x6a\xc8\x10\xa1\x68\x17\x85\x68\x17\x25\x60\x15\x31\xfc\x19\xf2\xdc\x70\xce\x0a\x0d\xa3\x11\xfe\x9f\xfb\x39\x40\x96\xe3\x8a\xc1\x1f\x2f\xcb\x32\xc4\x6d\xd9\xc2\xc5\x5d\x7a\xa8\x12\xac\xb4\x45\x6e\x18\xb2\xcd\x73\x22\x9c\x2b\xb0\x7e\x76\x61\xb6\xff\x40\x47\x18\x80\x08\xb3\xae\x50\x8c\xbe\x03\xf1\x33\xc7\x45\x16\xf2\x45\x16\x0e\xe4\xe5\x3d\xc8\xfd\x06\x98\x65\x32\x88\x46\x6f\x13\x67\x85\xb1\xc5\xc5\x78\x35\xf1\x5f\xfa\x19\xca\x3e\xf8\x29\xe1\x31\x24\xcf\xa5\x42\x1e\xbf\xec\xf7\x6a\x6d\x7a\x9f\xc8\x86\x64\x15\xe7\x93\xb0\xdd\x19\xe6\x53\x4e\xc6\x29\xb2\xdc\x54\x35\x6d\xcc\xf6\x51\x65\x5e\xa4\x14\x18\xd4\x3d\x52\xd9\x88\x3c\x72\x30\xaf\x99\x74\x0a\x2a\x7f\xd3\x79\xea\x6b\x6b\x3f\x1b\x7d\x20\xcd\x9c\x17\x3f\x4c\xf1\xf7\x1b\x71\xcc\x5c\x1b\xc3\x8a\x88\xd4\x05\x67\x68\xeb\xd2\x49\x4f\x9c\x2d\x40\x10\xf6\x82\x5b\x9e\x3e\x62\x1a\x24\x29\x4e\xa0\xd4\x4f\xf9\x55\x76\x24\xa9\xb4\xb1\xc7\x71\x4c\x7a\x2c\x5d\x71\x46\xba\x4f\x1e\xfc\x4c\x33\x65\x6c\x4b\x61\xd7\xe2\x0a\x32\xe1\xc3\x79\x2b\xd5\x07\x17\xf5\xca\x20\xf8\x85\x1c\x39\xbb\xc1\x5f\xed\x36\xfc\xff\x16\x00\xda\x8d\xcb\x32\x52\x7d\x7d\x2c\xc6\xd3\xc9\xe8\x33\x42\x38\xc5\x88\xce\x08\xb0\x72\xb5\x1e\x50\x77\x8f\x12\x27\x1e\x5d\xad\x7d\xab\xcf\x17\xa1\x43\x91\x53\x29\x4c\x20\xb2\x77\xd7\x0b\xe1\x17\xda\xfa\x7a\x2a\x97\xca\xd9\x34\x58\xe2\x3a\x45\x9f\x0b\xde\x5b\x15\x14\xca\x24\x85\x47\xe5\x58\x10\x4a\x04\xb4\xc4\x7f\xe5\xae\xe7\xac\x46\x8c\xf9\xaf\x99\xeb\x18\xb7\x56\xd3\xae\x31\x5e\x46\x17\x00\xce\x33\xc2\x39\xf0\x22\x19\xa0\x6c\x90\xd9\xa1\xa2\x05\xe8\x59\xcf\xfc\xae\x22\x0a\x23\x37\xc5\x87\xd4\xf9\xa8\x7d\x1c\xa1\xe9\x0f\x2e\xc4\x9a\x7e\x29\x33\xfa\x68\xef\x81\xa5\x2f\x98\x3a\x14\xac\xae\x31\x39\x99\x76\x13\xed\x2b\x55\x7c\x20\x0c\xde\x40\xc3\xb0\xa4\xc2\x20\x48\x61\xc1\xe7\xe8\x37\x94\xd7\x17\x1e\xf4\x7a\xa3\x37\xa1\x32\xda\xa6\x7a\x29\xac\x60\xda\xc2\xe0\x57\x98\x6b\xb4\x75\x19\xac\x75\x69\x1c\x20\x37\x91\x92\x25\x56\x0e\x2e\x68\x36\xa6\x3b\xee\xae\xf4\x8c\x4c\xd5\x54\x30\x9a\x0a\xf8\x6a\xe8\xd1\x19\xc7\x7c\x2c\xee\x22\x02\x28\xbc\xd8\xeb\xb9\x77\x7b\x18\x11\x29\x3f\xd5\x05\xd5\x85\x85\x07\x1d\x6e\x7f\x16\x9a\xf3\xc6\x89\x5f\x6f\xd6\xed\xa2\x8e\x41\xef\xe8\xe8\x81\x76\x9a\x6c\x17\x4c\x89\xe0\x5b\xe8\xe2\xeb\x00\xff\xe8\x79\xbd\x21\xbf\x42\x70\x2f\x19\x46\xf0\x32\xea\x24\x98\x99\x13\xa3\x35\x81\x3f\x82\x84\x1d\x45\x7e\x27\xe3\x05\x49\x80\x77\x30\x1f\x7a\x14\x24\x43\x54\x29\xb3\xe1\x70\xd8\xf3\x30\xe5\x3e\x88\x93\x68\x98\x90\x13\x0c\x4d\x08\xd6\xa0\x3f\xbd\xb4\x06\x3a\x9e\x6c\x1d\xa8\x1c\x1d\x66\xf6\x12\xa4\x6d\x0f\xf4\x55\x75\xa0\x4a\x7a\xd9\xad\x25\x46\xb0\x06\x13\xcf\x18\xa9\x9f\x8d\x12\xbf\xb0\x4f\x70\x18\x3a\xce\x53\x45\xfd\x15\xd6\x7a\x23\xf7\x1c\x59\x5f\x0e\x0a\x9a\x3f\x12\xfa\xe3\x00\xaa\x81\x13\xe5\x20\x69\x4e\x22\xf8\xe3\xc2\x00\x89\xaf\x3d\x45\x27\x1e\xdd\x0d\xa2\x16\xfe\x0a\x1b\x9e\x06\xb9\xe6\xe1\xab\xbb\xd3\x81\x2b\x7d\x7a\x28\x14\x88\xbe\x90\xfb\x6f\x73\xf4\x3d\xb7\x45\xf7\xbd\x90\x46\xf4\x28\x32\x96\xe0\xeb\xc6\x22\x6f\x72\xa3\xc8\x63\xbb\xc8\x93\x86\x22\x2f\x9a\x05\x24\xbb\x4e\x8b\x25\xf1\xf7\x3c\x27\xd1\x7b\x9d\x16\xfb\xc0\xe4\x46\xfc\x78\x09\xe8\x35\x09\x57\x34\x12\x94\xe2\x51\x46\xe6\x26\x98\x18\x98\x3a\x70\xa3\x44\x14\x75\xdb\x6d\x31\x6b\x05\xaa\x92\x30\x65\xda\x52\x82\xd5\x1a\x04\xc8\xc2\x5f\x1a\xf6\xed\x99\x25\xa0\x54\xe2\x13\xa6\x75\x2f\xa1\x99\x0b\xe6\x88\xfa\x88\x30\xd0\x6a\xc2\x73\x17\xef\x2b\x90\x02\x92\x3f\x18\xdf\x72\xf3\x5b\x5e\x96\x42\xa8\xca\x1f\x6c\x84\xda\x15\xc0\x4f\x9b\x50\xfe\x33\x0e\xd7\x99\x06\x4d\xc3\xfc\xac\x59\xa8\x72\x91\xe8\x91\x68\x64\xe8\x4e\xf9\x0d\xa4\xdc\x6f\x03\xe8\xca\xb1\x44\x1f\x08\xbe\xb7\xa3\x69\xf0\x97\xcf\x25\x1f\x10\xeb\x03\x12\xb0\x50\x15\x8a\xc6\xaa\x28\x43\x29\x09\x45\x63\x28\x1a\xf3\xa2\x2b\x2c\x8a\x71\x18\x03\xc1\x37\x83\xe0\x2f\xbc\x52\x12\xff\x9c\xe2\x53\x4c\x77\x46\xb6\xdb\xbb\x30\xda\xdd\xa5\x64\xf2\xcf\xb8\x26\x31\xe5\x1e\x28\x71\x65\xdb\x2c\x58\x6e\xf6\xce\x7a\xe7\xc1\x5c\x7f\x65\x95\xaf\x74\xeb\x6d\x59\x9e\xab\xf3\x0d\xce\x0c\xa4\x8c\xf0\x72\xc1\xe2\x3f\x07\xb3\x56\x3e\xa9\xbb\x15\xdd\x35\xdd\xae\xac\xcd\xb6\x6d\x42\x7a\xa1\x85\xf4\x42\x09\xe9\x85\x2d\xa4\xf1\x91\x0d\x6a\x02\x5a\xec\xfa\x9e\x04\x4e\x3e\x3a\x4b\xfc\x7b\x89\x5b\x99\x2d\x43\xb4\xd3\xad\x14\xa1\xf8\x7b\xa2\x67\xf8\x9e\x31\xc3\x7a\xfd\x09\xce\xf4\xff\xb2\xf7\xa6\xcd\x71\x23\xdb\x82\xd8\x67\x3f\xff\x09\xb2\xae\x2e\x05\x74\x25\x4b\x2c\x4a\xdd\xb7\x1b\xa5\x64\x05\x45\x51\x12\x5b\x0b\xd9\xa4\xd6\x26\x79\x39\x60\x15\x8a\x84\x54\x04\x8a\x00\x8a\x4b\xb3\xe8\xe8\x37\xfb\x8c\xed\xf1\xee\xb0\xc7\xcb\x3c\xef\xbb\xc7\x7b\x78\x77\x84\xef\x2f\x99\xf6\x1f\xf1\x59\x32\x13\x89\xa5\x8a\x54\xdf\x7e\xef\xbe\x89\x77\x43\x21\x56\x02\xc8\x7d\x39\x79\xf6\x63\x21\x9f\xf3\x21\x1c\xbd\x18\x31\x4f\xbe\xd8\x12\x40\xff\xba\x88\x08\xe2\x56\x82\xed\x1f\xef\xef\x7b\xf3\x0e\xfe\x12\x3a\x9c\x8f\x1d\xab\xc4\xea\x74\x71\x83\xb8\xc6\xfb\xc8\x87\x03\x58\x04\x6b\x8f\x15\x75\xf2\x8a\x5d\xb5\xe6\x8c\x61\x8f\x09\xc3\x66\x16\xd4\x08\x8e\x55\xe8\xf4\xe0\x56\x1c\xbb\xde\xb6\x18\xb1\x48\xd7\x19\x49\x38\x5d\x70\x57\xc3\xb8\x51\xcf\x99\x16\x7f\x64\xfa\x70\x5d\x25\x9b\x5f\x54\x39\x0d\x84\x7f\x77\x01\xc9\x36\x1a\x19\xde\xf4\x0b\x86\xf5\xf7\x00\xda\x30\xa9\xcb\xc7\xc6\xb5\xb9\xb4\x84\xb2\x2a\xf6\xc8\x1b\x3a\x2e\x51\x0e\x42\x0a\x88\xc9\x71\x4c\x6a\x22\xf0\xae\x0d\xb7\xaa\x46\x9c\x29\x1a\x43\x68\xee\x82\xa7\x91\x93\x63\x8b\x35\xfa\x0b\x1a\x71\x9e\x6f\x7b\x4a\x48\x8c\xd4\x63\xc8\x33\x98\x18\xe8\xe6\x02\x40\x32\x6b\x0c\x63\x85\x9b\xda\xe7\x5f\x76\x6f\x4d\x64\x31\x40\xbf\x7d\x11\x13\x51\x21\x7c\xfc\xa1\xc6\x3b\xb3\x1b\x27\x88\x08\xbb\x89\x9a\xd1\xf6\x6a\xf9\x74\xbc\x29\x4c\x38\xc3\x8f\x44\x7e\x17\x11\xc4\x7d\x8a\x5a\x97\x38\xd8\x66\xa3\x61\x6e\x7d\x49\x4e\x98\xf3\x49\x8f\x0d\xe0\xce\xc5\x86\xb0\xbf\xb4\xeb\x10\x3c\x37\x12\x1a\x8f\x01\x4b\x86\xc9\x85\x8d\xa4\x68\xb3\x98\x05\x3a\xb1\x6c\x5b\x8e\x65\x63\x0f\xae\x83\x58\xa0\xb1\x13\x07\x79\x83\xe5\x29\xd7\xec\xcb\xc3\x44\x91\x64\x58\xad\xb9\x52\x90\xcc\x43\x28\x1a\x58\x04\x60\xec\x91\x13\x46\xfc\x46\x15\x91\xc5\x7b\x3e\xfa\x27\x85\x53\x36\x85\xd2\x88\x71\x0b\x06\x78\x01\x11\x58\x9d\x4c\x18\x02\xaa\x98\x3e\xea\xc6\x2b\xd1\xb9\xbe\xa2\x73\x75\xe7\x82\xc0\x01\x10\x13\xe4\xb3\x46\xb1\x80\xa1\x06\x9f\x60\x6a\x0a\x27\x39\x80\x23\x07\x20\x00\x51\x08\x98\x22\x27\x21\xb8\x14\x42\x2a\xa4\xd4\x23\xee\xea\x58\x3c\xd1\xfd\xed\x58\x74\x8d\x3e\xaf\x40\x4b\x61\x20\xe5\x31\x11\xc8\x74\x10\x11\xd3\xdd\xee\x60\x98\xe6\xa1\xc4\x88\xf3\x31\x23\xbf\x30\x41\xf3\xfc\x12\x40\x76\x17\xff\xf6\xf0\x36\x90\x3d\xa6\x98\xc7\xfb\x80\x00\x53\x38\x80\x7c\xb2\x1e\x55\x2e\x1d\xbd\x65\x0b\xd2\x73\x26\x7d\x0d\xc8\x4c\x61\x51\xc6\x7a\x42\x11\x1f\x63\x09\xaa\x0f\x1f\x74\xd8\x63\x62\x77\x0c\x15\x04\x19\x53\xd0\x8f\x9a\xce\x8f\xc5\x3b\x8c\x35\xcc\xcb\x30\xe6\x65\x18\xbb\x2e\xf4\x1d\x9e\x7b\x6e\xb7\xe7\xc1\x77\xf8\x05\xaa\xaf\x87\x20\xc2\x7b\xcd\xd9\x8e\x30\x1b\xe4\x82\x5f\xf8\xba\x8a\x7f\xf1\x13\x95\x00\xea\x6d\x44\x5c\x7b\x05\xc3\xc7\x06\x86\x0f\x5d\x31\xea\x52\x4f\x13\x00\x60\x63\x35\x62\x4f\xcf\xd7\x3c\xcd\x17\xce\x9a\xab\x65\xc2\x43\xeb\x7e\x7e\x16\x58\xa7\xb0\x46\x83\x59\x5f\xf8\xdb\x5e\x80\x9c\xef\xbc\xe0\x0f\x16\x74\x9a\x79\xea\x72\xed\xbe\xc7\xc4\x79\x42\xfa\x2b\xaf\xe6\xb4\xca\x14\xed\x06\x39\x23\x9b\x40\x8a\x82\x67\x23\x3f\x49\x83\x27\xc3\xd8\xc7\x68\x33\xd1\xbe\x76\xd5\x0f\x50\xea\x2d\xda\xff\x6a\x52\x23\xe9\xf8\xbe\xbe\xa8\x13\x8c\x5c\x58\xc3\x4e\x79\x57\xe2\x28\x35\xbf\x8d\x9d\x43\xdf\x71\xbf\x70\x82\xc5\xac\x89\x1a\x6e\xb9\xac\xaa\x70\xf0\x34\x23\xb2\x06\x96\x47\x80\xcd\xc3\x59\x40\x19\x26\xdc\xe4\x34\x52\x05\xd3\x2d\x82\xe1\x79\x89\xb9\x51\x54\xd3\x09\xa4\x9e\x6e\x20\x8c\x02\xa6\x77\x38\xc8\xfb\x62\xa0\x08\xa3\x00\x6f\x81\x88\x8f\x45\xc4\x84\x91\x4d\x41\x29\xc2\x28\x58\x41\xda\x2a\x5a\x0c\x88\x34\x0a\x98\x34\x2a\x80\xed\xd0\xd5\x24\x43\x8c\xc0\x1e\x20\x7e\x33\x67\xd4\x5b\x38\xef\x77\x36\xd4\xbd\x1d\x55\xa8\xa9\x26\x31\x1f\xc1\xe0\xe7\xe7\xad\xe1\x7f\x28\x92\xdb\x36\x51\x98\x91\x13\x61\x04\x4d\xb4\xe6\x99\x66\xca\x17\x1d\xe1\x5b\x6b\x78\xa7\x34\x95\x1f\x91\x20\x47\x34\x1f\xa6\x31\x45\x50\x5a\x73\xcd\x90\xfc\xdc\x55\xb0\x92\x6e\xf0\xb2\xc2\x61\x54\x2a\x1b\xd8\x74\x1b\x96\xe5\xa7\x2b\xad\x8f\xe3\x45\xac\xa0\x8d\x1a\x2a\x42\xc5\x28\xb9\x36\xd9\x70\xc0\xb1\x3d\x53\x79\x75\x5a\xef\xe7\xda\x16\x08\x15\xa6\x67\x36\x11\x8e\x2c\x53\x3d\xd3\xb0\x01\x8a\xdb\xec\x7d\x15\x39\x79\xc3\xd3\x63\x31\x06\x13\x64\x5d\xa4\x88\xfa\x87\xc4\xb3\x40\x36\x06\xf2\x2d\x0c\xdb\x02\x90\x97\x31\x6e\xe9\x6f\x33\xc8\x8d\x44\xaa\x43\x6c\x0b\x54\xfb\x00\xa0\xd5\xb3\x78\x17\x91\xa1\x3d\x87\x0c\x23\x47\xa4\x1a\x32\x24\xd6\xb0\x47\x88\xb6\x5f\x61\x65\x0c\xe4\xd8\x6c\x00\x05\x84\xc7\xbb\x03\xbc\x19\x47\x36\x47\x03\x0e\xc0\x98\x21\xdd\x08\xe8\x81\x22\x7b\x23\x71\xc6\x62\xa4\xd8\x1b\x0e\x0a\x77\x90\xce\xad\xc9\x6d\x6e\xb7\x9e\x25\xdc\xba\x91\x62\xac\xca\x24\x14\x6a\x53\x23\x8f\xf8\xde\xe2\x04\x58\x91\x40\x72\x42\x3d\x81\xa3\x0a\x7b\xd3\x49\xba\x31\xe9\x33\xc5\x0f\x91\xaf\x80\x1c\x74\x40\x63\x63\xe4\xc4\x5b\xca\xff\x04\x26\x90\xb7\x11\xc3\xdf\xb8\xd9\xf6\x42\x76\x6b\xa4\x9e\x96\x04\xd6\x66\x93\x59\x59\x51\xab\xbc\x13\x15\x14\x52\x88\xb7\x12\x69\x32\xe3\xb6\x9c\x5a\x5c\x47\x9f\xf9\xb5\x06\x5b\x80\xab\xa5\xe5\x27\x47\x29\x42\x21\xbf\x85\xcd\x6b\x34\xa2\x85\x12\xbc\xd5\xe4\x48\xe4\x78\x8e\xb5\x21\x83\x92\x7f\x01\x0c\xea\x69\x71\xdb\x28\xdc\x61\x23\x1a\x9f\x1c\x06\x89\x25\x56\x64\x47\x84\xf0\xb3\xed\x53\xf4\x6c\xda\x6d\xe1\x4a\xae\x08\x96\x34\x43\x80\x6d\x48\x68\xe0\x34\x76\x9c\xa8\x1b\xac\x48\xdf\x0b\x56\x7c\xb7\x9b\x48\x9a\x38\x19\x5f\x9b\xd5\xd2\xfd\xe2\xce\x9c\xc5\x78\xfc\x72\xed\x99\x28\x5f\x41\x00\xc4\x4e\x21\xa4\xcb\x12\x4a\x6d\x6c\xee\x20\x4c\x0c\xd2\xbe\x88\x0d\xd1\xcd\x1f\xaf\x84\x86\x32\x81\xcb\xc4\x09\x9b\xb1\x7b\x6f\x19\x09\xd8\x88\x90\x14\xc5\xc5\x95\x3d\x3a\x0b\x8a\x3c\x19\x02\x62\xad\xa9\x92\xb4\x3b\x44\xce\xd6\x64\x42\x34\x8b\xeb\x25\x38\x94\x1e\x0c\xa5\xd7\x19\x75\x43\x39\x86\xb1\xc4\x72\xac\x87\x70\xe2\xc3\x52\xac\xf9\x56\xf7\x0d\x07\x7c\x2a\xab\xd4\x60\x36\x6c\x32\x61\xb1\xae\xb3\x4e\x7a\x1e\xa2\xc5\x17\x94\xee\xf9\xd0\x9d\xb6\x57\xc6\x08\x22\x5b\x57\x93\xe9\x5c\x98\xbc\x0e\xe5\xbe\x5f\xcd\x2d\x6a\x0d\x83\xf8\xb5\x2a\xf5\xa0\xbe\x54\x9d\x59\x93\x61\x2b\x70\xc9\x2f\xa7\x95\x44\x4c\x6f\x4a\x59\xa2\x25\xca\xc5\xac\xdc\xbc\x8b\x03\xdb\x89\x85\x25\x74\x2d\xb8\x6d\x33\x6c\x00\x5b\x51\xd5\x37\xd3\x6f\x29\xe1\x96\x98\x4f\x67\xbe\xa1\x0c\x17\x13\xb4\x52\xf1\xf1\x7d\x9a\x83\x9c\x31\x82\x9c\xb8\x99\x22\xd0\xf1\x51\x9f\x73\x8c\x94\x02\x0a\x92\x3a\x86\x49\x9c\xe0\x5b\xd4\xde\xdc\x67\x2e\x31\x7d\x88\x11\x7e\x42\x66\xe4\x7a\xc2\x5b\xf8\x31\x0a\xd4\x96\x10\xb6\xa6\x8b\x74\xfe\xa3\x12\x3b\xd1\xee\x67\x88\xfd\x4c\x25\x69\xc3\x98\x7e\xf6\x48\x92\xd4\x1c\xbb\x9a\x24\xef\x69\x79\x8e\x39\x32\x43\x19\xc3\xc7\xf4\xe1\x18\x3f\x0e\x9b\x29\x0e\x23\x35\xc3\x20\x30\x83\xef\x23\xe4\x7a\x61\x49\xab\xcb\x16\x8c\x1e\x97\xee\xcc\xd2\xfe\x52\x12\xa5\x2e\xf2\x4e\x58\xd6\x41\x68\x00\x2e\xf8\x7d\x57\x00\xb2\x1d\xb9\x26\x92\xa9\x9a\x6b\x4b\x63\xd6\x37\x1a\xb3\x63\x19\xe1\x1c\xa3\xa3\x80\xb1\xc0\x3b\xc5\xc7\xa0\x9e\x91\xba\x64\xe0\xfa\x8d\x2c\x84\x00\x85\x15\xee\x15\xe6\x0d\x20\x2f\x3f\x12\x07\x3c\xc7\x9e\x2c\x99\xb2\xbd\x73\x46\x61\xc9\xea\xc5\x5e\x03\x83\xf8\x59\xab\x11\xae\x2c\xa3\x4d\x64\xb8\xb8\x8c\x90\x58\x3d\x2d\xa3\x9c\x31\x5c\x69\xf3\x97\x36\xcf\x69\x8d\x9e\x76\xdc\x05\x8a\x15\xa0\x02\xdc\xf1\xe2\x4b\xe8\xe1\xa2\x5c\x86\x1b\x3c\xae\x73\x22\x90\x76\x53\xbe\xf3\x21\x53\xdc\x85\xfb\x05\xb6\xe6\xc2\xc2\x73\x98\x67\x0a\xe8\x88\xa1\x1d\x7d\x62\x8e\xca\xfb\x80\x72\x62\x4e\xb8\x98\x42\xd9\x76\x0b\x37\x06\xce\x22\xdc\x15\x63\x0a\x07\x29\xc6\xd6\x45\x10\xd8\x48\xce\x70\xfa\x9a\x6a\x14\x3e\xea\x3e\xf3\x51\x6f\x6d\x89\x28\xd7\x3b\x36\xe3\x82\x02\x3e\xbb\x16\x2e\x1b\xd0\xbd\x8a\xd3\x93\x20\x0f\xc2\x09\x0a\xf7\x6b\xe2\xf8\x7c\xbf\xfa\x65\x9d\x8a\xc8\x5a\xa5\x51\x54\x4b\x04\x95\x6f\xf3\x10\x3d\xe1\xe2\x55\x8e\x3f\x7e\x4e\x49\xa6\x70\x35\xf8\x78\xb9\x67\xdd\x94\xda\x4e\x2d\x36\x15\xd2\x95\x24\x42\x74\x42\xa4\x7c\x81\x3e\x53\x0e\x18\x49\xe3\x29\x9f\x21\x4b\xfe\xae\xbd\x60\xd8\x7a\x9d\x0a\x9f\x80\x3b\x96\x3d\x8b\x62\xe8\xd4\x80\x93\xf6\x55\x8f\xf6\x05\x26\x9e\x55\x58\x07\xd5\x78\xcf\xf5\x23\xa7\x56\xf6\x7f\x5c\x3f\x13\x15\x2c\x69\x14\x3b\xef\x89\xb7\x40\x6a\x74\x66\xc3\x02\x19\xa8\x90\x41\xb8\x2e\x61\xe7\x25\xa4\x1e\x50\x7b\x32\xfa\xb5\x2d\x69\x8a\xf2\x31\x82\x20\xcb\x5a\x05\x89\x85\xea\x60\x74\xbd\x6b\x21\x2c\x7d\x37\xf2\xec\x59\x3c\x8b\x4a\x9a\xbb\x9a\x75\xc2\x1b\x5b\xc9\x75\x1c\x96\xa1\x6b\x92\xe0\x71\x44\x74\x1b\x9d\x85\xba\x3f\x89\xcd\x10\x1d\xfa\xbd\xe0\x38\x1e\xf6\x03\x44\x1a\xad\x27\x11\xe7\xab\x9a\x6b\x1b\xcc\x86\x64\x33\x7b\x45\x94\x8d\xaf\x40\x44\xc2\x7c\x2a\x29\x0f\x60\xf9\x99\x19\x4c\xfe\x9e\x62\x05\xf6\xdc\x02\x8f\x3d\x22\x2a\x39\x9d\x4c\xe6\xb7\x70\x8e\xf2\x53\x94\xc2\x74\x25\x78\x62\x60\x44\x39\x5a\xf1\x82\xfb\x50\xa0\xd0\x8f\x66\xf4\x9c\x39\x6a\x0a\xe8\xc6\x39\xd0\xd5\xee\x78\x55\x6d\x7a\xd2\x7c\x54\x22\x44\x50\xeb\x6d\xeb\x16\x77\x78\x61\x32\xbb\xc5\xcb\x59\xc7\x51\x4f\x6d\x2e\x70\x45\x57\x68\x1f\xb9\x3f\xd0\x81\x90\x83\xb1\xba\x2e\xaa\x9a\x59\x5a\x05\xb7\xa8\xd3\xae\x66\x47\x07\x75\x2d\xb2\xe1\x0e\x67\xee\xda\x3a\xdb\xd4\x5c\xe0\x5e\x45\x3b\xf2\x20\x9f\x4b\xfb\xd7\x79\x10\x3b\x54\xb6\xe9\xa2\x81\xa2\x60\xc4\x13\x2e\x5b\x98\xc3\xac\x9b\x10\x70\x49\x1e\x06\x46\x7a\x15\xd3\x5d\x9f\xb7\xab\x58\xbd\x35\xe8\x9f\x5f\x91\x94\xf3\x1e\x89\xd0\x30\xe7\x91\x8f\x7a\x21\x91\x6c\xb0\xdc\x02\x51\xf0\xb4\xcb\xfa\xe5\xbb\xfb\x18\xcc\x82\xd4\x89\xd8\xf2\x34\xe8\xe8\x2e\x60\xf3\x09\x5e\x46\x5c\x9c\xc1\x5d\xa1\x8a\x27\xf8\x81\x6e\x16\xa8\x1c\xee\x85\x0f\x11\x50\x78\x4b\x28\x67\x1b\xc3\x9d\x22\xa5\xf3\x6a\xb2\x31\x79\x3c\x59\x45\x1d\xfa\xf1\xee\x83\x7d\x35\x6d\x0b\x0b\x6d\x29\xc7\xbb\xdf\xa0\x78\x00\xea\xa6\x22\xfb\xea\xf8\x47\x62\xbc\x7b\x1f\xfa\x04\x39\x7c\x93\x1d\xea\x05\x84\x3f\x02\x48\x8b\xc4\x2b\x50\x22\xc9\xd8\xc9\x25\x78\xa5\x65\xca\xf2\xe9\x52\xaa\x1d\x16\x5b\x77\x61\x01\x19\xcb\xd8\xa0\x91\xd7\xe0\xd1\x8e\x32\x7e\x69\xb4\x93\x73\x0c\x0a\x29\x19\x9c\x07\x3b\xa8\x52\xe6\xea\x49\x52\xdf\xf2\x50\x91\xa1\xa5\xcc\x66\xed\xab\xf5\xd9\xe0\xa1\xaa\xfa\xa2\x96\x15\x75\xbc\x58\x82\x41\x07\xaf\xcb\xd7\x23\xb1\x9f\x12\x8d\x08\xd9\xfb\xf7\xe2\xe6\x63\x50\xb7\x7b\x22\x20\x54\x88\x2c\x21\x4a\x32\xd1\xa7\xc4\x15\x19\x95\x45\x79\xae\xa5\x4b\xf0\xe7\xd1\x86\xdd\xc0\xda\xac\x06\xf8\xa2\xcc\x5d\xba\xda\x87\xfa\x75\x91\xb5\xc3\x00\x8c\x4f\x92\x7e\xec\x24\x74\x99\x27\x68\x21\x00\x67\xd0\x17\x21\xb2\xc7\x02\x12\xcc\x5b\x5a\x04\xb7\x81\x50\x92\x44\x9b\x0e\x56\x83\xc1\x00\x5e\xeb\x0c\x4d\x87\xac\xe1\x0a\x40\x76\xc7\xb2\x78\xb5\xd1\x44\x6b\x48\x07\xa8\x29\x63\xdf\x33\x66\x27\xd9\xb7\x56\x52\x40\x45\xad\x0b\xe8\xe5\xac\x1d\x96\xcf\x43\xc5\xf7\xe0\xfd\x1a\xbd\xab\x7c\xf3\xc5\x95\xcd\x07\x95\xc1\x99\x7f\x8b\x3b\x50\xdd\x0a\x0f\x5c\x7c\x57\xbc\x54\x36\x0d\xb1\xcd\xc4\x19\x49\x02\x7a\xd6\x7d\x3d\x74\x72\x9c\xe3\xb0\xd2\x2b\xb1\x2e\x0f\xc5\x05\x02\xc6\x43\xb7\xb3\x8e\xc4\xcf\xc5\xee\xba\x0d\x07\xd7\x09\x0e\xa2\xae\xc8\x85\x04\xd2\xec\x82\xe6\x05\x70\x37\x7a\x91\xe2\x0b\x44\x09\x5d\xd1\x9f\x4c\x4e\x78\xe8\xe7\x72\x58\xb8\xc4\xd7\x60\xc2\x2f\xc4\x39\xdd\x9f\x87\x8b\x72\xcd\xd0\x3e\x2b\x87\x5c\x60\x07\x00\x5c\x16\x38\xa9\x62\x97\xbd\x46\xb2\xa9\xb7\x78\x88\xf4\xd2\x86\xec\x77\xd7\xf8\xf5\x16\x24\x09\x61\x5e\x13\xaf\x20\x79\xc1\x6f\x57\xf5\xdb\x8b\x4e\x30\x81\xf4\x63\xef\x93\x08\x16\xe4\x3f\xe7\xf4\xbb\x9f\xbc\xc7\xae\x38\x43\x35\x65\x7c\x7e\x39\xd9\x54\x02\xec\x17\x72\x97\x67\xec\x95\xd8\x10\xab\x62\x4b\xec\xc0\x8c\xbd\xde\x17\x1f\xe5\x66\x64\xd4\x9b\x5e\xe4\x8c\x47\x96\x8b\x9d\xfa\xce\x47\x78\x2b\x3e\x16\xd0\x95\x73\xf1\xf1\x9a\x10\xc1\x37\x72\x80\x1a\x28\xe8\x14\xe1\x18\xa5\x03\xf2\xcd\xee\xe5\x3e\xd0\x7b\x34\x4d\x59\x02\x13\x80\x86\xea\x23\x80\xd7\x0f\x2f\x0c\x84\x74\x74\x12\xd5\x97\xb0\x96\x27\x37\xe3\xa5\xc3\xee\xd1\x64\x42\x28\x5f\x8e\x9e\x3e\x51\xdd\x7e\x23\x2e\x18\x2d\x1d\xc9\x60\xe1\x95\x18\xc0\xdf\x97\xe2\x18\xfe\x6e\x8a\x3e\xfc\xdd\x10\x67\xf0\xf7\xb5\x38\x81\xbf\x5b\xe2\x48\xce\x43\x17\xa8\x26\x71\x29\x4d\x5d\x96\xd9\xcf\xeb\xb2\x2b\xcb\x82\xa3\x88\x26\x1c\xf3\x15\x89\xd6\xbe\xc7\x24\xf6\x52\x9b\xbb\xa1\x54\xbb\x82\xc5\x24\x07\x1c\x5a\x4b\xa9\x31\xd7\xf0\xa2\x66\xa3\x21\x92\x18\x76\xf5\xd3\xd8\x09\xef\x69\x22\xcd\x75\x8d\xc7\x08\x5b\xa7\x65\xc3\xe2\x25\x99\x97\xa1\x53\xd2\x2e\x4e\xab\xfb\x5a\xe9\xdd\x18\x94\x7a\x88\x7b\x3c\x6d\xf6\x5c\xad\x81\x33\x44\x81\x57\x02\x7f\x98\x94\x26\xe9\x15\xbc\x2b\x62\x01\x4d\xe4\xe5\xf3\x8c\xde\xb8\x32\x21\x40\x3b\x33\x8d\x3a\x26\x74\xac\x76\x85\x18\xf2\xca\xc4\xb4\x26\x7e\x91\x6c\xb0\xb8\x9f\x5b\xd3\xe1\x61\x4e\xa7\x23\x38\xc8\xf1\x67\x85\xc1\x2a\xa4\xb6\x1b\x44\x0a\x6f\xf3\x22\x4e\x31\x3e\xdb\x76\x8b\xa8\xe1\xe3\x0a\xdc\x30\xea\x00\x0b\x9b\x84\x6e\x8d\x8b\x9a\x2c\x53\x15\x05\x59\xa0\x87\x1e\x61\x8d\xb0\x09\x15\x2c\xf5\xc1\x7b\x3c\xf9\x84\xe2\x65\x26\xcc\x5d\xd1\x5b\x44\xa1\x5f\xce\xfe\x0b\x16\x3e\x69\x7e\x77\x22\x46\x18\x77\x42\x65\xbd\x56\x9c\x6d\x3e\xde\x4f\xd0\x94\x1a\xf6\xf2\x6e\xde\xe9\xa1\x18\x71\xc7\x09\x42\x0d\xe0\x38\xbd\x8f\x9c\x63\x31\x40\x7f\x10\xc7\x48\x69\xa7\xf0\xf3\x0d\x1c\x42\xfc\xab\xb6\x60\xda\x1d\x77\x97\x3c\xc3\x7d\x04\x40\x93\x2e\xf6\x00\xd0\xa0\xe0\x27\x90\xf2\xa5\xcb\x3a\x2a\x40\x38\x1e\x23\xc1\x7e\xbc\xbb\xbc\xcf\x32\x57\x78\x19\xcc\xcb\xc7\xa4\xa8\x03\xb0\xe4\x31\x94\x38\xce\xf1\xac\xae\x05\x39\x8e\x5d\x6f\xc3\x7e\xa2\xf9\x39\x03\xf0\xf0\xd1\xf7\x4e\x7d\xbd\x6a\x67\x4e\x1f\xbe\x59\x1a\x49\xa5\xe5\xd0\x94\x07\xb1\x8b\xb2\x9c\x5d\x14\xe4\xfb\x79\x9e\xe6\x79\x3c\x2f\x7b\x68\x38\x09\x74\x4f\x6f\x65\x5c\x52\xf6\xe8\x0c\x51\x33\x8a\x78\x47\x57\x6a\x17\x03\x6a\x87\x80\x41\xd1\xd2\x43\xb9\x2d\x12\x12\xb5\x86\xdd\xc4\x19\xc0\x8c\x02\x14\x4e\x9c\x91\x18\x10\xbc\x22\x59\x2c\x8a\x13\x42\xc3\xfd\x39\x96\xbd\xce\x31\x1a\x59\x38\x58\xcb\xf1\xbe\x98\x87\xc2\x00\xd7\x50\xfd\x63\x30\x99\x44\x54\x56\x0f\x82\xac\x44\x69\xfa\xa6\xe7\xd1\x1a\x21\xf3\x16\xe4\x79\x95\xbb\xf7\x2d\xb2\x53\xbf\xf3\xe8\xe7\x83\xe2\x5b\x36\x33\x09\x70\x88\x79\x99\x77\x34\x2f\x33\x6b\x45\xfe\x09\x2c\x66\x40\xbf\xa8\xc1\x7d\x12\xa4\xa9\x7f\x44\xaf\x54\x92\x8b\x7c\x6b\x8a\xcc\xcb\x66\x86\x4a\x04\xe8\x86\x3c\xaf\x32\xcb\xb8\xb9\x28\x33\x19\xa1\x0e\xb4\xbd\x37\xea\x2c\xb9\xf2\xce\x94\x05\x7c\xa3\xd4\xb3\xd2\x7c\x0d\x49\x6f\x00\xb9\xd8\x16\x3c\x85\x65\x84\xb5\x9a\x0f\x8b\xeb\xc7\x6b\x16\xc2\x82\x91\xd2\xce\xc0\x2c\xe4\xb1\x4c\x77\x07\xfb\x00\xd5\xc3\xee\x31\xea\x3c\x04\x5e\xae\x35\x75\xcc\x9a\x52\xda\xf4\x2d\x63\xd3\x37\x5c\xab\x4e\x5f\x2d\x77\x9f\x96\xfb\x44\x9c\xe1\x6e\x85\x66\xc4\x09\x24\xe0\x0e\x57\x2a\x3c\x7d\x79\xb6\xb0\x70\x06\x0f\x27\xb8\x58\xf8\xd5\x2c\x28\xa9\x53\xf5\xf3\x5e\x8e\xe0\x98\x8f\x64\xc3\x0a\x9f\x07\x58\xcd\x31\x67\x1b\x71\x17\x8e\xd0\x02\x3f\xff\x0e\x97\x4d\x50\x08\xb7\x87\xda\x95\xf3\xf2\x12\xa0\x8d\x5d\x4b\xc8\xa1\x10\x4a\xaf\x02\xdc\xea\x35\x08\xd4\xd1\xc2\xc2\x91\x0d\x8b\x8f\x6a\xa3\x28\x40\x1b\x97\x45\x5b\xe2\x99\x7a\x49\xa5\xeb\x2f\xea\x5e\xf8\xde\xba\x8f\x7c\x1a\xe4\x28\x4e\x93\x29\xda\x90\x54\x3d\x76\x1c\x27\xea\x86\x2b\x63\x6f\xbc\x82\x22\x46\x34\x5e\x80\x55\xc0\x9f\x18\x71\xf4\x50\x8e\x51\x28\x82\x02\x6e\x4b\x5e\xfc\x91\xd5\x5d\x0d\xd6\x1a\xd0\xfa\x1e\xfa\xbd\x4f\x93\xc9\x20\x36\x57\x87\x44\xaa\x65\x10\x77\x0f\x02\x2f\x44\x61\x96\x2a\xe4\x59\x77\xca\x9b\x4a\x4d\xca\x2f\xc3\x64\x72\x94\x14\x2b\x3a\x4a\xd0\x62\x53\x64\xb5\xf5\x3c\x99\xca\xf6\xee\x46\x39\xec\x2f\x8a\xbe\x90\x91\x49\x1c\x3e\x0a\xa6\xa2\x4e\x73\x4c\x96\x97\x7c\xa4\x1b\x68\xca\x8c\x1e\x2d\xa4\xcf\xa6\x8b\x1d\xf3\x96\xdc\x6a\x03\x7a\xbf\x58\xfc\x84\xe6\xa3\xf0\x16\x4d\x4a\x03\x91\x35\x81\x60\x2e\x7d\x54\xe5\x32\x62\xbf\x8b\x60\x31\x17\x58\x5c\x91\x99\xaa\x07\x2f\xa3\x7e\x81\xc7\xf5\xc8\x76\x06\x96\x1b\xd5\xe0\x25\x57\xd8\xbc\x4e\xce\x82\x81\xad\x58\x35\xb0\x83\x4b\xa3\xa0\xde\x48\x13\xdd\x20\x42\x4c\xd9\x88\x2a\xe7\x10\x02\x9f\x47\xe3\x8c\x9e\xe1\xb7\x20\x74\x7e\x56\xe8\x4d\x35\x34\x65\xcd\xd6\x46\x2e\x8e\xbd\xb5\xd9\x3c\xef\x55\x0c\xf5\xc2\x18\x2c\xea\xe5\x87\x0a\x52\x67\xd7\xaf\x16\x48\xad\xcd\x5c\x68\x00\x1f\x09\x6e\x3a\x75\x30\x98\x30\x81\xc4\x69\xea\xcf\xb1\x02\x9a\xbe\xfa\x4d\xd5\xef\x58\xfd\xf6\xd4\xef\x50\xfd\x8e\xd4\xef\x40\xfd\x1e\x67\x9e\x16\xf9\x1e\x8e\x07\x83\x20\x47\x23\xa9\x9d\xa8\x8b\x2e\xfb\x5c\xdc\xa4\xad\xc3\xcb\x2c\xd8\x1c\x0c\xd2\x20\x33\xc6\xc9\xae\x86\xec\x25\xc0\xcd\x85\x75\x1f\x33\x6e\x23\x96\xea\x75\x2b\x25\x97\x9a\xe2\x71\xd6\x0a\x2e\x82\x1e\xaa\x83\x75\xe2\x3c\xea\x10\x6e\x09\x9d\xae\xd1\x66\x3e\x35\x53\x6a\xb4\x7b\xbf\x8b\xc8\x5f\x21\x2d\x02\xed\x1a\x91\xa1\xce\x9b\x61\xb4\xa1\x4f\x1f\x28\xf4\x1c\xc9\x68\xa5\xf3\x16\xa0\x8a\x5b\xe0\x6a\x1f\x6a\x5a\x89\x10\x76\xab\x65\xf8\xa9\x91\xbc\x6d\x2f\xd1\x6c\x92\x82\xe8\xf5\x5d\xad\x2a\xe0\x9d\xc8\x79\xe6\x93\xc6\x61\xae\x8c\x53\xf6\x48\xd6\x84\x47\x23\x3b\x79\xe9\x7b\xd0\xfd\x95\xc5\x36\xdc\x9e\xbf\x86\x7e\x63\x54\xbb\x15\x4b\x63\xe4\xb9\x2d\x22\x9d\x5f\xb3\x18\xa2\x4a\x0b\x30\xc9\xf5\xa5\x0b\xf2\xe8\xa4\xfb\x0e\x25\xa0\xa4\x68\x04\xe5\x8d\x76\x67\x7e\x92\x12\xde\xc8\x73\x91\x11\x61\x58\xc3\x27\x77\x43\x5d\xfc\x1b\x7a\xa8\x4f\x19\xd6\x5c\xc4\xdf\x15\x05\xf8\xda\xe6\x09\xbb\x61\x1a\x89\x16\x16\xb6\xb3\x56\x16\x60\xf0\x00\x58\xa4\xbc\x7f\x51\xae\x01\x0e\x05\x6c\xab\x79\x33\xb0\xf9\x35\x53\xd2\x28\x99\xb3\x3a\xf7\x3c\x0a\xd8\x33\xa5\xdf\x69\xdb\xc6\x7c\xb0\x94\x62\x1e\xf9\x79\xc1\x79\xd4\x8d\x24\xc5\xf3\xdd\x68\x5f\x29\xbe\xbf\xcf\x99\xf5\x96\x86\x8e\xb5\xac\x15\xe1\x3e\x79\x57\xb1\x97\xea\xa5\xbf\x22\xad\xc5\x7a\x5a\x74\xf7\x46\xea\xe6\xac\xf3\x68\xa9\xb9\x14\x27\x0d\xb1\x67\x54\x7b\x6d\xa3\xda\x6b\x34\xc1\xfb\xee\xd5\x4a\xc8\x9a\x2e\xaf\xc8\x39\xc9\xc6\x64\x62\xd2\xab\xd0\xf4\xee\x6f\x34\x2e\xfc\x10\xca\x7d\xbd\x4f\x9f\x9d\x57\xc4\x91\xc4\xec\xac\x39\x09\x0d\xfb\xb9\xa8\x3c\x59\x78\x49\x8a\x74\xcb\x28\xd2\x5c\x86\xa6\x26\xb0\x30\x2f\x01\x3f\x7f\xad\x79\xaa\xc1\xee\x7d\xd6\x45\x76\xaf\xfe\x84\xaf\xd4\x0c\xdf\xe0\x1f\x20\x0c\x7c\x34\xb2\x43\xf3\xc0\x07\xfb\x40\x0c\x23\x03\x41\x64\x90\x86\x2f\x07\x0e\x66\x11\xef\xe8\x35\x7d\x37\x96\x77\x50\xe7\x97\xfb\x44\x97\x63\x65\x90\xc4\x3f\x50\x24\xd5\x95\x7d\x65\x55\xf6\x95\xae\xec\xcb\xbc\x32\xf8\xee\x92\xea\xe6\x6f\xb8\x1a\x1c\xba\xa4\x02\x40\xe6\x2c\xbc\xa2\x37\x5f\x6b\x7a\x03\x93\x5d\x9c\x0f\x0f\x6e\x2b\x7c\x10\xf8\x60\x34\x5c\x33\xa0\x4c\xa8\xc0\x37\x38\x05\x48\xab\xe0\x0d\xc2\xfa\xc6\xb8\x08\x80\xfa\x59\x0b\xf9\xad\x5a\xa4\x4c\x92\x62\x6f\x67\xba\xbe\xcd\xd5\x75\xc1\x38\x23\x66\x05\xcd\x78\x8e\x91\x2a\x27\xd4\x42\x66\x37\xd7\xe8\xc8\xf5\x6f\x0a\x5b\x21\x67\xff\x6d\x16\x95\xbc\xca\x76\x3d\x4e\x44\xda\x6f\x25\x2d\xbd\x2c\xa9\x28\x25\xe6\x66\xc0\x78\x81\x9b\xbb\x96\x54\xaa\x38\x54\xb0\xd1\x54\x54\x36\x8e\xa4\x44\xfd\x16\xe5\xaf\x91\xdb\xc5\xbe\xe7\x42\x0f\x6b\x76\x28\xe8\xec\x95\x52\xaf\x0b\x5a\xe9\x78\x34\x8a\x93\x8c\x10\xd1\x23\x3a\xe5\xb9\x31\xc4\xbc\xfc\x7e\x32\x99\xb7\xae\x69\x1b\xcb\x64\xae\x69\x11\x65\xad\xb9\x70\xd1\x19\xa6\x53\x50\x0e\x02\x18\x58\x82\x15\xd3\xa6\x0e\xe1\x2e\x71\x42\x95\x5d\x56\xde\x93\xc4\x56\xa3\x49\x6c\x63\xdf\x48\x3e\x0b\x59\x51\xdb\x52\x86\x48\x2c\xfb\xd4\x58\x9a\x41\xa3\x0c\x97\xa0\x7e\xa8\x54\x67\x71\xf8\x71\x2b\x8a\xa3\x75\x00\x1e\xab\xc9\x11\xec\xdb\xa3\x90\x0d\x2f\x99\xc2\x24\x6b\x9e\xd4\x6c\x98\x9e\x44\x11\x40\x07\x55\xcd\xde\xa2\x76\x31\x62\xad\x79\x27\x7b\x6e\xae\x1b\xd6\x33\x5b\xc8\xd2\x8f\x48\x92\x1a\x6d\xf8\xdd\x7d\x8f\xd5\xfa\xd9\x05\x41\xe6\xbd\x22\xe3\xd1\xe7\x45\x40\x14\xda\x45\x0b\x39\x2d\x25\x92\x44\x39\x0f\x2a\x7a\x35\x51\x0e\x4c\x72\x43\x01\xfc\xda\x4a\x02\xe2\xd7\x39\x3b\x25\x33\x32\xde\xbe\x3c\x08\x40\x9b\x4d\xbe\x0d\xd8\x0e\x77\xda\x0d\xd7\x43\x1f\x76\x2e\x85\xb5\xc9\x55\x53\xec\xce\x15\x3d\x15\x75\x33\xed\xb3\xc5\x53\xee\x84\x6c\x5f\x2c\xe4\xc7\x45\x39\x03\x12\xb8\xcb\x0b\x9e\x57\xac\xa1\xa5\x89\xbe\x58\x03\x09\xa8\x8e\xb9\x67\x95\x31\x6e\xe0\x76\xdb\xc8\xb4\x40\x95\xd6\xb6\x68\x97\xa5\x27\x05\xbd\x2a\xa5\x82\xb2\x19\x3b\xc4\x67\x23\xed\x75\x54\xf8\x52\x46\x66\xac\x04\x27\x92\xa6\xb4\xa4\x8a\x96\xbe\x48\x61\xf3\x69\x13\xfe\xa2\x55\x27\xe1\xfe\xb4\x73\x72\x5b\xfe\x98\x6d\xf9\x63\x82\x32\x40\x0a\xec\xcb\xb8\x0e\xc8\xf4\x92\x12\x16\x6a\xfb\xdc\xd0\xb7\x6a\xd7\xa9\x9d\x02\x52\xe3\x6d\xbb\xca\x60\x60\x05\x35\x3d\x60\x70\xde\xae\xe5\x4d\x64\xf8\x0b\x54\x1f\xc8\x64\x91\x26\x7a\x49\x37\x35\xa5\xb1\x91\x69\x4c\xef\x8c\xfc\x54\x52\x08\x04\x64\xdf\x23\x67\xe0\xbe\x2b\xe6\x97\x50\x0c\x5a\x28\x3e\xf8\xac\xe2\xc5\xb2\xc7\x49\xc5\x3c\xb4\x66\xa4\x61\x17\x65\x73\x1a\x6f\x98\xb7\x20\x98\x19\x3d\xc1\x3c\x5c\xd3\xd0\x15\x96\xcd\x69\xb1\xb5\x7e\x61\xfb\x77\xf1\xaa\x02\x48\x9c\xeb\x09\xdc\x62\xd2\x4b\x6d\xb2\xfb\x9c\xa4\xcb\xf6\x99\xc5\xd6\x4e\x92\x29\x2e\x59\x34\xfd\xc5\xa5\xca\x53\x72\x34\xab\x17\x78\x19\x68\x8f\x94\x8b\xed\x5a\x55\xc9\xc8\x45\xa7\x47\x51\x17\x4e\x59\xd2\x8c\x28\x7a\xb2\xf1\xb8\x63\x70\x52\x56\xc2\x74\x49\x5b\x32\xd4\xf0\x86\x34\x01\x03\x32\xa4\xf7\x3d\x1f\xb0\x53\xdf\x25\x8d\x1a\x43\x31\x70\xc7\x70\x43\x59\x12\x7a\x7b\x4e\x69\xdb\xb6\x6d\x9f\x75\x89\xc5\xe9\xce\xe0\xac\x09\x75\x12\x2b\xec\x6e\x34\x1d\x81\xd3\xf8\x86\x15\x1c\x42\x56\x48\x2e\x9d\xcd\xb1\xc5\xd8\x86\x33\xaa\x4d\x2b\x32\x63\x07\xa1\xec\x9a\x7d\x84\xee\xda\x04\xbb\xbd\xcc\x26\xd8\xf0\x8e\xcf\x08\xf3\x80\xac\x8b\x7c\x79\xc5\x98\x4f\xa5\xc6\xba\x63\x09\xad\x3b\xa0\xab\xa3\xa2\x27\xa7\x81\x4c\xe0\x53\xae\xee\x3c\x7c\x38\x62\x75\x65\xd9\xdb\x1d\xee\x0b\x67\xd0\xfd\x36\x73\x06\x68\x50\x16\xa2\xb9\x0c\x4c\xbf\xfb\x70\x89\xa7\x00\xa8\x93\xce\xe2\x62\x60\x18\x60\x09\xb9\x21\x19\x38\xce\x31\x96\x39\xe6\x32\x08\x7c\x4c\x31\xcb\xa1\xd2\x60\x61\x61\x60\x86\x99\xea\x54\x8d\x3b\x86\xc3\x1b\x77\x1d\x34\xb1\xd8\x2e\x6c\xfc\xf5\xcf\xd8\x72\xda\xb2\xa2\x7e\xeb\x85\xd2\x29\xee\x3d\x40\x91\xc8\x28\x21\x41\x12\xb1\xd9\xb6\x77\xa2\xde\x85\x78\x02\x54\xc5\xf1\x94\xed\x18\x7b\xec\xdf\x91\xb7\x63\x9d\xcb\x53\xb2\xd5\x63\x96\x71\xa8\x34\xc8\xb1\x2a\xdb\xbf\x69\x9d\x1b\xd5\x8b\xa4\xaa\x0a\x80\xf2\x5e\x5c\x63\xd2\xd8\x00\x34\x4b\xa3\x78\x26\x56\x90\x85\xb7\x2e\x55\xd5\xe9\xb5\xda\x53\xae\x97\xb6\x24\x94\x8b\x1c\x87\x14\xc6\x84\x2f\x62\xe5\x45\x54\x9b\xa7\xa0\x85\x5b\xbb\xd6\x1d\x61\x69\x65\x94\x1f\x02\x74\xbc\x9a\x95\xba\x65\xb9\x24\x40\xf3\x50\x6c\xb3\xe0\xee\x48\x1a\x28\x4c\xca\xa3\xbe\x65\x21\x1e\xa2\xf7\x9e\x94\x9c\xc0\xa0\xc6\x91\xf1\xd8\xa0\x0c\x8c\xc2\x5c\x69\x9e\x6c\x74\xe2\x82\x6d\xe2\x9a\x0d\x00\x7a\x65\x00\xb0\x7d\xbb\x8b\xec\x16\xe0\x3d\x80\x79\x8c\x64\xa2\xee\x32\xb2\x51\x2f\xc0\xcd\x9d\x5f\xec\x46\x9e\x72\x4d\xbe\xfc\x73\xb9\x93\x6b\x9b\xda\xfc\x9c\x2b\xb5\x5d\xb9\x42\x5e\xdf\xbe\x78\xb1\xe0\xc6\xec\xeb\x98\xcd\xa0\xb9\x4e\xd8\x89\x86\x65\xd0\x38\x8c\xe3\x61\xe0\x5b\x42\xb6\x80\x35\xd7\x60\xc1\xd4\x5c\x24\x2e\x8b\xc1\x02\x41\x57\xa6\xb2\xb4\x44\x75\x36\x7d\xda\xf1\xc2\x39\x08\x34\x23\x42\xdd\xe8\xbe\x51\xfd\x80\x1a\xf1\xa0\x01\x14\xe8\x1e\x12\xcf\xc8\x23\xcb\x16\x9b\x77\xb4\xa5\xd1\xea\xba\xf3\xb1\xbb\xdf\xb1\x10\xc1\xa5\x0e\x1c\xf8\xb2\xd1\x8f\x9a\x2c\x46\xf2\xa1\x71\x4b\xf9\x19\xc9\x3b\x9c\x65\xed\x9b\xc1\xc2\x5b\xd9\xe0\x55\x5d\x53\x08\xd3\x25\xb9\xb8\x7a\x16\x10\x2f\x4c\xef\x0b\x4b\x6e\x79\x5b\x60\xab\x7a\x1c\x4a\x1a\x57\x91\x81\x86\xaa\xae\xb0\xa3\x12\x5e\xc6\x07\xe8\xc9\xcd\x09\xeb\x06\xa3\xdc\x4e\x6d\x93\xf2\x9a\x8d\xa8\x7f\x2a\xde\xcc\x8b\xe8\x83\xa4\xa2\xb4\xd6\x6c\x66\x46\xc5\xcc\xba\xb3\x77\x33\x02\x43\xc4\x09\x73\x79\x14\x49\xf7\x22\x20\xcf\x4a\xda\xe7\xfb\x05\x29\x1e\xb9\xa8\x32\x66\xce\x06\xac\x58\x52\xdc\x70\xaf\x92\x8a\x75\x52\x01\x47\x27\x4e\x00\xf6\x92\x7c\x6e\x93\xd3\x0a\xd2\xbe\x22\xbe\xe4\xee\xbe\x5b\xe2\x12\xb0\x23\x32\x22\xb1\x89\x63\xe0\x31\x1a\x1f\x43\x11\xc0\xe3\x77\xdb\xb5\xfc\x82\x55\x73\x63\x92\xc1\x5a\x3e\xd3\xb6\xff\xd3\x25\x9b\x29\xf0\xa2\x7c\xbe\x02\x1d\x5c\x33\x2b\x18\x9f\x7e\x9c\x91\xcf\x92\x6e\x24\xb9\x1a\xe0\x6a\xa2\x82\xab\xe5\x32\x8b\xa4\x18\x8a\x44\x85\x20\x57\xda\x67\x25\x3f\xad\x56\xb9\x47\x45\xfa\x47\x85\xcf\xeb\x24\x05\x82\xdf\xf8\x2f\x03\xc2\x30\x71\x61\xe6\xe2\x82\x4b\xd7\xd0\x0b\x64\xa8\x2e\x66\x94\x6b\x27\xf6\x57\x83\x15\x96\xbc\xc0\x5a\xb7\xd7\xb3\x64\xaa\x73\x4f\xc3\x10\x2d\x12\xa1\xda\xd3\xa1\xa1\x2d\x73\x55\x93\x82\x2b\x52\x96\x0a\x20\x91\x6a\x42\x93\x94\xa7\x42\x47\x9c\x46\x0d\xc0\x9a\x83\x61\x95\xb4\x55\xd2\x7f\x48\xea\x1c\xf4\x3b\x6e\xc1\x5f\xf9\xa9\x9d\x29\xaa\xf8\x84\xad\xba\x26\xb5\xf8\xdb\xa5\xd3\x4f\x1c\x80\x6e\x1c\x78\xe7\xc1\x54\x12\x83\xf5\x0e\xea\x14\xe5\x10\x5c\x6a\x45\x39\xeb\x82\x87\xfb\xd9\x29\x3a\xb4\x7a\x5b\xdb\xac\x1f\x78\xdb\xa6\x59\xab\x7c\xa5\xf8\xf3\xa4\xc0\x6c\x8f\x52\xbc\x42\x08\xc0\x59\x6c\xeb\x9a\xbb\x83\x98\xf6\xf9\xed\x48\x0c\x1d\x34\xd5\x96\xc4\x34\xb1\x90\x26\x48\x23\xc4\xad\xe2\x00\x93\x49\x42\xd3\xc1\x15\xc3\x55\xa9\xd0\xcb\x50\x91\x36\x88\x5b\xd6\xb9\x89\xd4\x0e\x99\xb7\x88\x03\x13\xa2\x49\x6c\x1e\xaa\x0b\x27\x02\xf0\x2f\xef\x8d\x9e\x66\x78\x70\x3d\x9b\x07\xff\xa1\x76\xbe\xd2\xc0\x7b\x71\xab\xf9\xba\x53\x9c\x2f\xaa\x6d\x3d\x2e\xce\xd7\xd3\xcf\x5f\x92\x22\xff\xc7\xb8\x33\x0f\xd4\xb3\xbd\x8f\xdf\x9b\xda\x11\xd9\xae\xc1\x48\xae\x32\x49\x5c\x2e\x2d\xed\xd0\x20\x5f\x03\xeb\x95\x25\x20\x14\xde\xa1\x36\x13\xa2\xee\x48\x2e\xf0\xa2\x7e\x6b\x5f\x46\x5a\x0d\x06\x39\xa1\x8c\xc9\xb0\xad\x72\x98\x2f\xab\xc5\xfd\x25\x88\xa4\x9b\x9d\xee\x5c\xb1\x70\xa1\xaa\xad\x44\x1d\x41\x5f\x05\x64\xe4\xed\xd0\x35\x8b\x7e\xf6\x60\x5e\x10\xcb\x47\xaa\xa9\xc6\x95\xd5\xf7\x05\x5a\xa8\xba\x19\x03\xb7\x1b\x78\xa4\xdf\xa0\x5a\xb7\xf8\xbe\x61\xdd\xea\x0c\x30\x52\xc5\x9f\xe7\x39\x0d\x42\x7b\xd9\x98\xf1\x68\x21\x5c\xb5\x2d\x76\xb4\x20\xbb\x63\xe3\xf8\x3c\x6f\x25\xc3\x66\x36\x58\x52\xa2\x64\x63\xb7\x1c\xa8\x0f\xc6\x7c\x39\xa9\x37\x5f\x0e\xc5\xc8\xe6\xee\x86\xf9\x79\xaf\x72\x4a\x1d\xfb\xd8\xb2\xd1\x29\xcd\x8e\xf2\x46\xe1\xe4\xa2\x3a\xc8\x8c\xae\x66\xd9\x5c\x80\x3c\x08\x6a\x65\x3b\xfc\x12\xed\x53\x7c\x12\x85\xf0\x5b\x1c\xda\xb0\x70\xc2\x08\xbe\x95\x21\x52\xa8\xf2\xd4\xab\xc1\x4f\xfd\x50\xaf\x20\x86\xa6\xb4\x99\x44\xf4\xd5\x20\x34\x99\x3c\x86\x2d\x25\x9b\xc4\xe2\x5d\xb2\xe3\x12\x2a\x42\x73\x31\x7b\xd8\xee\x06\xb6\x3a\x78\x6e\xb0\xa2\x51\x49\x8b\x2b\x6c\xd6\x7e\xf6\x06\x0b\x50\xfe\x65\xbc\x2f\x59\x9a\x60\xca\x4f\x80\x2b\x48\x35\xee\x55\xad\xd9\x8a\xbd\xd9\xfc\xd0\x42\xbe\xa6\x18\x0b\x7c\xe6\x2c\x25\x66\x96\x92\xa9\x26\x96\x30\x2d\x2b\x4b\xb4\x25\xa6\x4c\x8d\x2b\xda\x14\x72\xc1\x8c\xd8\x36\xd0\x4a\xf3\xa8\x2a\x66\x2f\x20\x26\xbb\xb0\xf0\x3e\x76\x06\xae\x18\x53\x62\x8c\x1a\x4b\x03\x79\x2c\x2d\x2e\x47\xe8\x18\x2c\x6f\xd1\x39\x4e\x1d\x77\x71\x48\x8a\x46\x4b\x2b\xe8\xf3\x3e\x5a\x81\xa1\xea\xc2\x6a\x2c\xc7\x1d\x55\x89\xd2\x39\xc2\x42\xe8\x67\x48\x75\x1b\x75\xcd\xc4\x60\x32\x41\xff\x53\xa9\x1c\x49\xc5\x5c\x22\x16\xc7\x40\xc6\x70\x49\x15\xc8\x93\xb8\xd0\x4d\x55\xb1\x73\x32\x99\x9c\xcd\x2b\x12\xf1\xb6\x2d\xe4\x2b\xe8\x28\x2f\x92\x39\xf3\x62\xc8\x75\xb0\xba\xa7\x00\xc8\x8c\x8a\x6e\x70\x1f\x1e\xa1\x73\x2a\xb2\x36\xe3\x39\x38\x5a\x58\x98\x1f\xb0\x37\x16\xa8\xfd\x08\x1a\xe8\x4b\x03\x4b\xce\x16\x9d\xe1\x62\x1f\x19\x71\x30\x39\x09\xfa\xdd\x3b\xeb\xf8\x5d\x67\x4c\x42\x47\x9a\x21\xd4\xb5\x1a\x96\x7a\xea\x7a\xd8\xcf\x31\x8e\x3c\x46\xd4\xdf\x38\x81\x5b\x58\x18\x74\x07\x92\x06\xee\x0d\x38\x76\x0e\xaa\x35\xab\x39\x42\xd3\xb1\x88\xbc\x21\x02\x96\x5d\xaa\x51\xcc\xfb\x93\x49\x79\x02\x44\x8f\xee\x22\xd2\x13\x27\x25\xca\x81\x38\x86\xee\x2c\xc1\x00\x81\x18\x3e\x51\x7a\x85\xb7\xda\xb3\xa4\x08\x6c\xdf\x5c\xe8\x4f\x03\x48\x25\xa5\xf7\x05\x35\x41\x75\x6d\x5e\x52\xd2\x12\x80\x7e\x1e\x91\x00\xcb\xef\x03\xca\x01\x2d\x36\x4e\xfc\x8b\x77\x7e\x98\xa1\x72\x17\x8c\x02\x8f\x61\xd4\x52\xef\x48\x29\xd3\x85\x1e\x35\xb2\xc4\x0f\x87\x88\xa3\x84\x14\xd0\xaf\xa5\x9f\xbd\x93\x5c\x76\x01\xb4\x01\xa0\xc1\xa8\x45\x6a\x8b\x31\x66\xc2\x30\x68\x21\xa8\x55\x72\x0d\xa6\xc0\x30\xeb\x30\xf2\x4a\xe7\x1b\x07\x8d\x7f\x29\xd0\xba\x20\x3b\x5a\xfb\x68\x02\xd1\x96\x28\x8e\x58\x48\x2e\xbd\xe3\x3c\x36\x11\x47\xd5\xd6\x04\x7d\x56\x2c\x96\xe3\x09\x29\xc5\xde\xf6\x61\x4b\xe5\xe6\x18\xdc\x1c\xa1\xf5\xe3\xb0\xb5\x46\x6d\x5b\x54\x56\x2f\x54\xe4\xfc\xe7\x78\xfb\xac\x40\x9b\xf9\xac\x1e\xc8\x58\x20\x65\x18\x5a\x74\x01\x00\xc5\xe5\x02\x79\x36\x9a\xbd\x02\xd3\x3a\x12\x20\xfb\x40\xf9\xa4\xd5\x16\xd4\x6d\xcf\x80\x68\xab\x9f\x39\x37\x31\x5f\x0c\x25\x9b\x82\x2a\xb4\xb0\x74\x91\x82\x19\xd6\x39\x6c\x89\x76\x83\x66\xb2\x5f\xd6\x7c\x5a\xca\xb5\x49\x73\x93\xa3\x58\xa9\x0f\xb5\xeb\x3e\x92\x85\xaf\xce\xb1\x3c\x35\x07\xd9\x00\xc7\xac\x0c\x4e\xd2\xb9\xa0\xa9\xe4\x78\x09\x2b\x79\x92\xb5\x93\xcf\x3d\x4b\x8c\x2c\xd3\x47\x94\x2d\x16\xc5\xd5\xb0\x57\x61\xf0\x7b\x2d\xb7\x1d\xd6\xdc\x6a\xa1\x60\x69\x72\x5c\xc2\xe9\xe6\x91\xbf\xf0\x19\xc0\x42\xef\x5b\x02\xa3\x5d\xf4\xef\xe3\x69\x98\x90\xc8\x86\x02\x09\x7c\xc2\xe7\xe7\x0d\x8c\xf0\x12\x68\xa5\x04\x00\xf0\xb3\x01\x01\x80\x78\xbd\xcb\x74\x6e\x38\xfd\xf0\xa0\xe0\x07\x9a\x28\xc0\x93\xce\x29\x43\xa1\x6e\xbf\x77\xf6\x06\xed\x17\x51\xa1\x1c\xb3\x3a\x8b\xbd\x00\x71\x01\xf8\xc3\x97\xff\x6e\xb6\x2f\x76\x6d\xaf\xfe\x67\x55\x1c\x6e\x1a\x3b\xcf\x60\x22\x5d\x64\xe0\x79\xf5\x1a\x7c\x8a\xe7\xa7\x98\x7c\x90\xaa\xd7\x3b\x50\x16\x5d\x90\x43\x3b\x5a\xb6\xfa\x74\x52\x46\x83\x82\xba\x5a\x02\xaa\x05\xbb\xae\x6b\x99\x5f\x2a\x20\x37\x47\xf6\xa1\xe6\x20\x3d\xef\xd8\x10\x26\x57\xa3\x90\xf2\xad\x25\xc8\xb2\x0b\x64\x74\x0d\x70\x10\xb8\xf9\x36\xdc\x8f\x95\x92\xdf\x59\x42\xae\x6a\x53\x76\xce\x0f\x96\x70\xc6\xca\x49\x51\xa8\x38\x84\x74\x14\xf7\x83\xd7\x30\xae\x85\x85\x72\xe9\x3c\xba\xf4\xfa\x30\x40\xd0\xd0\x40\x5a\xd5\x92\xdc\xd8\x4d\x1b\xb7\x7d\x4b\x9e\x1a\xaa\x56\x9d\x20\x2a\x98\xbc\x8a\xd1\x0f\x7d\x43\x4f\xa7\x2d\x8e\xae\xea\xba\x5d\xc3\x2e\xf5\xe6\xeb\x09\xa2\x0b\x6b\xab\x90\xf8\x6c\xe6\xd2\x22\x5f\x3a\x22\x5f\x7c\xc6\x25\x9f\x6b\x4d\x6d\xa0\xc8\x93\xa8\xcb\x72\x48\x6f\x3b\xd7\xe2\x45\x88\xa9\xdd\x9b\x02\x51\x3e\x6f\x51\x90\xe7\xd5\x89\xae\xd2\xfe\x5a\x43\xbe\xb8\x08\x77\x2c\x81\x45\x68\x51\x85\xd3\x3d\x8a\xa3\xe8\xa7\x18\x28\xcc\xe2\x6c\x6d\x5b\xb3\xc1\x43\x61\x9d\xf8\x58\x6a\xd2\x57\x79\xda\xb3\xb5\xf1\x8a\xf4\xdc\x3c\x89\x6f\x6f\x9e\x47\xa5\x2c\x45\xf3\xd9\x46\x21\x98\xb6\xa8\x46\x60\x9c\xb2\x4b\x10\xf6\xe9\x98\x9a\x39\x4e\x71\x5b\xc1\x87\x8a\x67\x79\xe3\xb0\x91\xfd\x8b\xb8\xec\xbf\x03\x80\x3e\xb9\x0d\x49\xe5\x98\x39\xa7\xc8\x40\xdd\x17\xe4\xca\x83\xea\xd5\xab\xb3\xca\xee\x29\x11\xef\xb2\x8f\xec\x8e\xbd\x2e\xaf\x43\x5a\x18\xb2\x48\xb0\x84\x27\xb5\x1b\xb5\xed\xd9\x6b\xf4\xb4\xfb\x5d\xcc\x9a\x89\x3f\x98\xb7\xae\xc7\xeb\xfc\xca\xe8\x2c\x5a\x52\x92\x6a\x9d\xb6\xda\xe0\x6b\xeb\x73\x55\xe7\xb0\xee\x4c\x7f\x6b\x49\x42\x66\x9f\xe9\xcc\x6a\x67\xcb\x6e\xa7\x86\x15\x55\x2d\x1d\x59\xa5\x1f\x57\x1b\x42\x65\x49\xcd\x40\x01\x2c\x7d\xfe\x87\x6c\x37\x2f\x6d\x31\xcf\x3f\x95\x21\x96\x45\xec\xbc\xb2\x37\xf9\x14\xd6\x87\x8a\x51\x05\x64\x76\x49\x87\x69\xd5\xae\x98\xfc\xfb\x93\xea\x96\x95\xe3\x45\xe9\x2a\x7d\x6c\x29\x85\x4e\xa5\x5b\xbb\x5b\x3e\x1a\xae\x02\x32\x69\xb1\xc8\xed\xa6\xb6\xea\x9a\x7a\x53\x6a\x4a\x6f\x9e\x6d\xd6\x40\x66\xe5\x64\xb4\x69\xc9\x85\x2d\x04\x43\x22\xbb\x99\x27\x39\x12\x57\x39\x85\x8c\x7b\xe5\xda\x61\x56\xe8\x6d\xd6\x83\xfe\x39\x5a\xd0\x82\xd9\x18\xc5\xf0\x3f\x4c\xea\x58\x3c\x7a\x33\xb4\x29\x9c\x9d\x92\x99\x02\x9b\xe2\xe4\x30\x06\xe8\x33\x52\x94\x4c\x4c\xf4\x89\x54\x86\x1c\x8e\x8f\x42\x48\x05\x5d\xdd\xb4\x2f\xc6\x6e\xd7\xdf\x1d\xef\x6b\xd9\xae\x87\x0f\x12\x32\x71\x22\xad\x71\xd8\xfd\x4c\x23\x64\x15\x3e\xd4\x1a\xdf\x23\x4e\x26\x49\xb1\xcd\x44\xde\xca\x9d\x17\x06\xb4\x8b\x03\xeb\x0a\xda\xf0\xeb\xd4\xf7\x16\x16\x10\x21\xee\xd8\xda\x95\xb6\xda\xa2\x1a\x77\x3d\x88\x8c\x72\x45\x63\x0a\xe2\xaa\xbc\x23\xa0\x3f\xae\x95\x25\x8d\x87\x12\x86\x9c\xa0\x53\x4a\xe3\xf7\x93\x21\x21\x6b\x06\x22\x86\x38\x99\x94\xac\x7f\x50\x29\x36\x2c\xe8\x57\x02\x64\x45\xfd\x43\x35\x77\xc6\x70\xd1\x12\x1b\x84\x35\xda\x66\x6f\xd2\x8a\xbe\xa3\xf6\x23\x17\x58\x42\x2b\xd2\x0f\x0f\x11\x3d\xde\x05\xfc\x18\x21\x6f\x8d\x90\xea\x74\xea\x29\xb0\xb5\xeb\x13\x65\xff\xf4\xfb\xa8\xf1\x17\xeb\xa6\xcd\xbc\x6f\x5c\xf0\xe3\xa9\x72\x05\xa0\x0e\x89\xdb\x4d\x34\x48\xb2\x0f\xda\xbb\xe9\x0c\x4c\xa5\xe0\x98\x90\x01\x9a\x72\x70\x39\x4f\x3e\x89\x4d\x3f\xbb\xf0\xe0\xb1\x91\x4a\x29\xd6\x4a\x90\x6f\xf9\x98\xec\x65\x33\x25\x7e\x4e\xd1\x40\x30\x0f\xbf\x82\xae\x5c\x43\xda\xa1\x29\x5b\x26\x49\xbf\x8b\x3e\xea\x65\xa4\x38\xdf\xf8\x80\xd7\x22\xbe\x43\x1d\xfe\xdd\xb0\xd9\xde\x77\x91\xd7\x78\x75\x4d\xea\xa4\xa9\x15\xe6\xc4\x0e\x54\x57\xb9\xf1\xd5\xc6\x26\x00\xce\x8c\x84\x8f\xec\x3a\xe0\x81\xd6\x8e\x8e\xc8\xf2\x50\xc5\xac\x32\x32\xca\x82\xbd\x4a\x24\xc3\x2e\xf3\x96\x91\xce\x88\x11\x18\x03\x2c\xdd\x44\x12\x7b\x61\x21\xb6\xfc\xde\x28\x27\xfb\xb9\x3e\xb3\x13\xd6\x84\xd3\x28\x3a\xe0\x64\xd7\xa3\xd5\xa0\x0c\xcf\x6d\xa0\x4b\xce\x0f\x69\xab\xda\xc2\x9c\x4a\x8e\x32\x58\xfe\x50\x45\xd3\x99\xb8\x6d\x8c\x01\x65\x1d\x84\x51\xd0\xb7\x4e\x2b\x0a\x77\x90\x2a\x40\x91\x8d\x64\x37\xa5\xd9\x0a\x1b\x40\x21\xc0\xcb\x1e\x9e\x71\xd2\x12\xa1\xcc\x80\x8d\x05\xbe\x77\x1e\xf8\x46\xd1\x3d\x39\xaa\x85\x5c\xa5\xd0\xa2\x67\xac\x68\xc4\xa8\xff\x85\x67\xc1\xf5\xaa\x5f\x03\x66\x4e\x12\x71\x48\x3a\xf1\x14\x3c\x29\x90\x08\x8a\x90\xac\x41\x96\x2f\x49\x39\xba\xf0\x12\x6b\x59\xc2\x70\x32\x8a\x7f\x04\x34\xc3\xaf\x81\x60\x08\x7e\xdd\xd6\x0b\x8e\xde\x64\xf5\x01\x45\x25\xfa\x66\xcc\xbe\x65\x2d\x27\xb6\x8d\x76\xb0\xd8\x68\x3a\x4e\x8c\xd7\x98\xe1\x16\xa0\x6f\xfb\xc0\x70\xd1\xde\x95\x83\xd4\x3c\x2d\x5e\xff\x04\x6c\x48\xd1\x43\x85\x2a\x5e\x72\x5b\x59\xfc\x06\x3d\xb0\xac\xf9\x28\xe6\x6c\x66\xca\x40\xdd\xd6\xcf\x79\x3f\xad\x12\xad\x4e\xbc\x9a\x89\xe3\x5c\x09\xf9\x75\x26\xa0\x87\x96\x4c\xc7\xac\x92\x2a\x1b\x34\xa5\xb2\xa0\xaf\xca\x94\x94\xb7\xda\x6e\xe2\x91\xb8\x28\x8f\xf9\x01\x20\x25\x5a\xcc\x8f\x78\xb4\x82\x46\x20\x45\x71\x1d\x2c\xa6\x25\xd7\xa9\xef\xf4\xa1\xc1\x11\xbb\x79\xff\x2f\x33\xd1\x77\xed\x00\x51\x59\x5c\x5b\x78\xb3\xae\xf0\x4b\x18\xee\xde\xde\x9d\x85\x46\xa1\x86\x20\x2e\x0f\x1a\x0d\x6e\x4b\x63\x46\x9f\x13\x55\xef\x02\x0a\x06\x86\x12\x76\x40\xe2\xde\x5b\x06\xc8\xf6\x2d\x32\x74\x00\xac\x3d\x8d\x2d\xbf\xe8\x91\x7c\x1d\x39\x8d\x86\xf2\x3e\x67\x1c\x0b\xc4\xb0\x88\x4d\x6b\x22\xa2\xb8\x74\x08\xab\x3a\x53\xae\x38\xf0\x4b\x1b\x27\x89\x6d\xa5\x0b\x58\x2e\x8a\x1e\x61\x46\x22\xda\x14\x02\x3d\x2b\x77\x3d\xea\xf4\xe3\xb9\xe0\xd7\xcb\xec\x5c\x98\x32\x43\xdf\x03\x74\x6d\x99\xc1\x73\xe7\xfc\x38\x1c\x06\x96\x7d\xa1\xd5\xcf\xb0\xdc\x4f\xd5\x9c\x1d\xfe\xa5\xb4\x27\x72\xc9\xb0\x65\xbb\x56\xb7\x19\xe2\xd8\x29\x19\x87\x66\xc1\x09\x2c\x5f\x16\xec\x04\x59\x06\xc8\x38\x85\x23\x7e\xae\x85\xa6\xec\x52\x46\xa1\xa4\xa6\x1b\x27\x81\x03\xc8\xe9\xd5\xb5\x40\x4b\x28\x74\x52\x72\xa6\xe2\x21\xa0\x7d\xfe\x38\xff\x1c\xb5\xc2\x13\x34\x50\x48\x21\x8f\x4e\x62\x5e\x36\x8a\x1e\xa3\x51\x34\x40\x4b\xf4\x5f\xa2\x62\x7e\xa2\x95\x64\x16\x24\xa3\x18\x3b\x34\x99\xbc\x80\xd3\x24\x31\xbc\xe3\x5c\x53\xce\xdd\x6d\x88\xbe\x5c\x8d\x1d\x27\x6a\x05\x69\xcf\x1f\xd1\x77\x57\x99\xf2\x35\x1b\x93\x46\x73\x60\x3f\x38\x03\x38\x3d\xe7\x59\x77\x2b\xf3\x4a\xd9\xb0\x02\x94\xd8\xa9\x26\xac\x6f\x77\x1a\xa2\x71\xd4\x20\x16\xf4\xbd\x7b\xbf\x9a\xe3\xf7\x6f\xb6\x5f\x48\x28\xd4\x30\x4f\x9a\x2b\x6d\x5e\x78\x8d\x61\xdc\xf7\xd3\xe3\x7c\x2a\xe9\x4b\xba\xdb\x68\xce\x35\x9b\xcf\xb2\x66\x63\xbf\xe1\x36\x1b\x7b\x51\xa3\x93\x1f\x96\x7e\xd1\x33\x22\x5a\x5c\x93\xc3\x78\x8d\x9b\x90\x7f\x78\xd8\xea\xc7\xb0\x59\xd4\x8e\x1e\xc1\x77\x53\xfe\x63\x26\xce\x58\x12\x10\x23\x6b\x0e\xb2\x35\xee\xce\x35\xf7\xa2\x83\x83\xc0\x69\x34\xa3\x66\xc3\xc5\xa7\xbb\x0d\x76\x4a\xe2\x9b\x3c\x1d\xe8\x46\x33\x6d\x36\x3a\x98\x55\x4d\x2c\x41\x6d\xc7\x54\xe1\x38\x07\x07\xd9\x9c\x9c\x83\x7a\x00\x17\x74\xdd\x39\x29\x89\x60\x9c\xeb\xce\xdd\xbd\x3b\xe7\xcd\xc1\x57\x53\xf9\x48\x8e\x9b\x06\x14\xa1\x8d\x8b\x69\xa4\xc3\x42\x01\xf4\x9e\x9b\x84\xfe\xe1\x30\xe8\xa0\xd8\x04\xd6\xf3\x3c\xcc\x8e\xe7\x9c\xf8\xf0\xa3\x3b\x77\x85\x9d\x39\xc6\xa9\xb9\x86\x14\x3a\x7c\x70\xfc\xee\x71\x3e\x47\x04\x3f\x3d\x0b\xa2\x9e\x29\x73\x0d\xf3\xe2\x84\x5e\x74\xa8\xac\x41\x7c\xa1\xe3\x0e\x34\x86\xbc\x08\x9c\x78\xd5\x8e\x73\x84\xde\x83\xf0\xe5\xdc\x64\x42\x1d\x80\x31\x62\xfc\x35\x6c\xba\xd9\xc0\xee\xc2\xc8\xc4\x1c\x4e\x0b\xcc\xca\x5d\x28\x11\x77\x1b\xf8\x1c\xc0\xf3\x81\xda\x75\x0d\xf2\x49\x04\xdd\xa4\x2f\x58\xc5\x6a\x92\xf8\x97\x39\xee\xd1\xfa\x18\x87\x11\xd4\x99\xb3\xc4\x81\xc6\xcd\x1c\xe8\xc4\x9c\x9a\x70\x28\xa6\xe8\x0c\xc3\xc1\x86\xe6\xdc\x39\x9c\x03\xaf\xc1\xdd\x81\x49\x51\x3b\x01\x0a\xc1\xf4\xf0\x74\x5e\xca\xa7\xa9\x1d\x9f\x4b\x53\x82\xb1\xd3\x13\x27\xa6\x04\x4c\xa9\x6b\x3c\x52\x0c\xd1\xab\x11\x80\xac\x4b\xb5\x5f\xe5\xb1\x38\x0f\x9d\x4b\x57\xf1\x6b\x2f\x35\xfc\xb9\xb4\xe4\x64\x71\x11\x7b\xd6\xfc\x1e\x05\xf6\x50\xdb\x0f\x55\x24\x92\x92\xa9\x8a\xde\xa6\x18\xa3\x5c\x60\x74\xf1\x26\x7a\xbe\xa6\x2b\x4e\xe8\x6f\x3d\x56\xa4\x67\xea\x0e\xfd\xc5\xdb\x37\x45\x3a\xa5\x5d\x73\xef\x98\x26\xea\x3b\x80\x0d\x7b\xd4\x02\x22\x06\x85\xaa\xc7\x37\x56\x3d\x7b\x4c\x4b\x66\x40\xf9\x9b\xa1\x6e\x89\x5e\x5b\x92\x98\xf8\x06\x3a\x95\xbb\xf0\x02\xf0\xa3\x8f\x1a\xfb\x9a\x87\xc6\x20\x49\xc1\x60\x35\x26\xd4\x48\x03\x40\x7a\x7c\xed\x0a\x81\xa2\xb8\xaa\x17\x5e\xdc\x21\x1e\x3a\x9e\x3a\xfe\x68\x0e\x21\xdc\x06\xcc\x43\x8f\x4f\xc2\x34\x45\x2a\x90\xbe\xa7\x4e\xd0\xd2\x6f\xd0\xca\x9f\xbd\x80\x33\x1a\x66\xdd\x68\x70\x09\x97\x35\xa5\x33\x25\xac\x4a\x16\x6d\x66\x5d\x7b\xc5\xcf\x35\xc5\x95\xad\xa6\x99\x19\xdf\xcd\xb1\x4a\xcd\xd4\x9b\x1b\x37\x29\x52\xc8\x46\xe8\xa8\xb0\x20\x3a\xbf\x0f\x10\x38\xf0\x13\x74\x14\xa0\xc6\x4e\x72\xca\x62\x7d\x14\xcb\xa6\x75\x34\x8c\x0f\xfd\x21\x85\xf4\x81\x9b\x20\xd6\x76\xdc\x8e\x36\xe4\x8e\x91\x3c\xc5\xc3\x0c\x50\x1c\x15\xb2\x73\x93\xee\xa5\x4e\x4f\xc6\x9c\x69\xe4\x76\x5c\xf4\xc6\x41\x08\x53\x67\x2c\xc7\xa6\x1d\xee\xf1\xb0\xeb\x7b\x18\x19\x43\x2b\xdf\xe7\xa8\x15\x7b\x43\x55\xbe\x3e\xc8\x0b\xbb\x75\xd5\xc6\xd0\x49\xb2\xcb\x75\xec\x2a\x07\xb9\x60\x17\x26\xc0\x92\xa2\xd5\xe3\x55\x07\x75\x78\xd5\x51\x26\xce\x0b\x3b\x6c\x74\x23\x22\x53\xb8\xb0\x51\x42\x42\xc2\xae\xc9\xe4\x0d\xd2\x60\x05\x73\xa4\x5b\x56\x85\xbc\xb6\xee\x09\x99\xf0\x1d\x94\x51\xeb\x63\x7b\x2c\x55\xe8\x94\xd9\xce\x45\x0b\xc3\xb6\xc4\x18\xf6\xfb\x8f\x81\xa3\x64\x14\x36\x09\x75\x14\x17\x04\x37\x14\xd5\xe6\x10\x29\xf1\x62\xb6\x4b\x33\xa0\x9c\xb0\xd1\xa7\x9e\x8e\x17\xdb\x51\x1a\x06\x34\x90\x2b\x46\x6b\x72\x0b\xab\x03\xb4\x12\xe0\xbe\xf6\x51\x0b\x04\x3c\x6d\xb7\xf9\xb6\x92\xd4\x20\x05\xc3\x4a\xa7\x1c\x5a\x8a\xca\x50\x6d\xae\x16\xeb\xc2\x55\xab\xec\x2c\x37\x69\xfe\x7b\x79\x9c\x29\x25\x0d\xf3\x2d\x69\x58\x83\x54\x30\x95\x40\x1c\x2e\xea\xa8\x45\x2f\x5c\xed\xf2\x39\x45\xef\x55\xca\x65\x12\xfa\xc4\xc5\x10\x01\xbb\x43\x34\x93\x1d\xee\xcb\x11\x6a\x70\xd8\x1e\x5f\xf1\x65\x8d\x98\xaf\x24\xc9\x8e\x64\x51\xfd\x93\x7c\xab\x23\x2e\xa7\xc1\x63\x45\x4b\x93\xfd\xd5\x5a\x5a\x9a\x64\xbd\x5b\x09\x2a\x6f\x24\xd8\xc4\xfc\x21\xa5\x13\x8f\x1c\xcf\xa6\x5e\x7e\xd9\x29\x87\xf7\xb0\xa3\xd1\x06\x29\x57\x1b\x06\x2c\x48\x39\xcd\xda\xb5\x95\x49\xf3\xf0\xd2\x96\x33\x7d\x23\x99\x16\x46\xf6\x8e\x62\xd6\x6b\x38\xdd\x75\x61\x60\x0f\x62\xdb\x67\xf9\x81\x7c\x1e\x97\x22\x82\x1f\x62\x06\x4b\x52\x64\xef\x47\x0a\x95\xd4\xa5\x80\x2f\x1e\x45\x6f\xb1\xe4\x3c\xb5\x5b\x3f\x9f\xf7\x32\xd3\xd5\xf6\xf6\x38\xe3\x9a\x30\xe7\x97\x49\xe7\x1c\xf1\x6f\x2b\x7c\x5f\x0b\x2d\x2b\x24\x75\x99\x09\x7a\xe6\xa3\x3d\x28\x52\xd0\xee\x3d\xb4\x2d\x42\x9e\xd5\x14\xc9\x78\x86\x84\x89\x09\x55\x62\xb1\xeb\xd6\xec\x23\x95\x21\x19\x93\xa1\xd2\x91\x22\x79\x8c\x49\xae\xd2\xc0\x57\x0d\x43\xfd\x48\xbe\x8b\x73\x5f\xc5\x4d\x30\xfa\xf7\xca\xfb\x75\xd6\x71\xcf\xfd\x95\xa4\xcb\x7e\x22\x1d\x72\xbe\x69\xe9\x40\x58\xd2\xa3\x38\x67\xce\x37\x9b\xef\x8c\x2f\x1c\x3c\x5b\x4d\x4b\xca\xb4\x53\x00\x10\x0e\x4d\x1d\x60\x6a\x6c\x3f\x62\xc9\x56\x6e\x77\x3d\xab\xa8\x28\x9a\x4b\x62\xb1\x0c\xd1\xfb\x1a\x07\x6d\xa2\x50\xa4\x89\x51\x4f\x0c\xbb\xc7\x01\x33\x70\x31\xb0\x2e\xc5\xfc\xf2\x54\x64\x92\x6b\x00\x1a\xdd\x24\x68\xf5\x83\x81\x3f\x1e\x66\xa9\x13\x05\xad\x4d\x92\x94\xa1\x2a\xb6\x80\x2f\xa3\xb0\xf7\x09\xde\x8a\x47\x58\x2a\x62\x02\x79\x13\xf9\x5f\x84\x5e\x8a\xd7\x98\x7c\x0c\xb4\x85\xd8\xc0\xd4\x7a\x92\xc4\x89\xd8\xc2\xe4\x13\x35\x30\xf1\x18\x9f\x5e\xfa\x80\x87\x7f\xc2\xd4\x2b\x92\xe1\x88\x57\x98\xe6\xa6\xc4\x2a\xa6\xb7\x83\xa3\xf5\x8b\x91\x78\x81\xe9\x1d\x92\xbf\x88\x8f\x98\x46\x91\x2a\x57\xfb\x06\x77\x47\x0e\x52\xc4\x93\x58\xbe\xb2\x9f\x1f\xc5\xf2\x85\xfd\xfc\x2c\x96\xce\x33\xac\xe2\x1c\x2e\xca\xf8\x1c\xe6\xf2\x59\xdc\xea\xc7\x3d\x3a\xa1\xe2\x07\x80\x91\x56\xee\x56\x16\xab\x56\x4f\x63\xf9\x24\x46\x05\x99\xcd\xf3\x68\x2b\x89\x47\x41\x92\x5d\x8a\x77\x68\x00\xf6\x96\xbe\x98\x8c\xcf\xb1\xee\x03\xf1\x1d\x5d\xfa\x8d\xdf\x36\x9a\x59\xec\xbc\x8d\x73\x1a\xe0\x9e\xce\x39\x31\xb8\xb1\xdb\xfa\xa2\xeb\x74\xe5\xde\xde\x9e\xe3\x4e\xe0\x92\x4b\xe6\x5a\x4d\xf5\x62\xdf\xbd\x77\x84\x34\x03\xe4\x40\x4c\xe1\x0e\x90\x0e\x1f\x62\xf9\x32\x74\x3e\x98\xd9\x7e\x44\x8e\x68\x60\x1c\x1f\x62\x71\x87\xbe\xc1\xdf\x0f\xf1\xc2\x02\x72\x1d\x3f\xc4\xc8\x2b\xa2\xfb\x1d\xa5\x4f\xb1\x78\x1a\xcb\xc7\x71\xab\x17\x84\x43\xf1\x9e\x18\x96\x43\xc0\x66\x5e\x87\x27\x41\x3c\xce\xc4\xb7\xf4\x71\x30\x8c\x61\x5e\xbf\xa7\xaa\xbe\xa7\xd9\x3c\x0a\x32\x6b\xd8\x3b\x97\x27\x87\xf1\x10\x79\xb0\xdf\x03\x60\xf2\x31\x1b\xfc\xe5\x6c\x5b\x7a\xe6\x36\x07\xc8\xfb\xf3\x45\xe0\xcb\x37\xcc\x5d\x17\x11\x65\x8d\x7c\x5e\x9f\xe0\x0c\xe6\x7b\xfd\x22\x0b\x22\xc4\xf2\xb0\xb6\xc8\x17\x89\x8f\x73\x39\x52\x0d\x6d\xa4\x28\x53\x08\x12\xa4\xc7\x44\x48\xa5\x43\xd4\x43\x02\xe2\x1f\xb2\x87\xbe\x88\xf1\x29\x0d\x32\xdd\x7f\x9f\x1a\x63\xc1\xb7\x48\xa9\x40\x8a\x59\xde\x00\x4d\xf3\x35\x4d\x16\x94\x4b\x81\xea\xa7\x4f\x63\xfc\xf4\x2e\xf0\x3f\xbd\xf4\x47\xe8\x34\xc0\x17\x3d\xdf\xd6\xa2\xca\x92\x4b\x75\x90\x21\x33\x8a\x40\x88\xa1\xf7\xd5\x03\x5d\x51\xa0\x9c\x30\x05\x8e\x9a\xe9\x36\xc0\xaa\x25\x80\x18\xf0\xe9\xba\x47\x48\x4c\x02\x60\xda\xb0\x4c\xe0\xf0\x0c\x0b\x0d\xb0\xf9\x44\xe4\x2f\x2c\xe0\x14\xe2\xb4\xf8\x80\xf2\x1e\x11\xd7\xb4\x83\xad\x23\x04\xd3\xc0\x24\xf2\x9d\xab\xb6\x87\xf6\x49\xe8\x81\x43\xb6\xaf\x55\x13\x11\x77\x14\xdd\xe7\x36\x2e\x62\x00\xda\xe6\xb5\xf6\x3f\x83\xae\x52\xa0\xc6\xdc\x1d\x0d\xea\x10\xd2\x0c\x8c\x50\xc9\xa7\x85\xf7\x1b\x8f\x68\xe4\x8b\x01\x7d\x18\xd0\x22\xf5\x92\x00\xce\x30\xbc\x1f\xf8\xe2\x18\x27\x2b\x4c\x9f\x84\x51\x08\xc7\xba\x4f\xb9\xfa\x94\xeb\x53\x70\x89\xab\xd7\xf7\xc5\x99\x8f\xdb\xe7\xc4\xbf\x10\x27\x9c\x0a\x23\x71\x44\x39\xe1\xef\x6b\xf4\xf1\x80\xc7\xed\xc8\x17\x97\xf4\x12\xfe\x7e\x8a\x4d\x9d\xf0\xe5\xd2\x17\x07\xd8\x0c\x71\x4f\x37\xe0\x34\x1e\x52\x35\x89\x0f\x07\xf5\x44\xac\x53\xf6\x57\xeb\x4f\x57\x5f\x6f\xbc\x5d\x3f\xd8\x78\xf5\x64\xe3\xd5\xc6\xeb\x0f\xe2\x82\xde\x6f\x6d\xee\x6c\x14\xdf\x9f\x53\xe1\x51\x7c\xee\x2c\x8b\xfb\xcb\x2e\xc0\xf9\x35\x5f\x9e\xfb\xf0\xbb\x8d\xbf\x14\x51\x66\xc7\x97\x3d\xbf\xdb\xf3\x5b\x8f\x3e\xbc\x5e\xdf\x39\xd8\x5a\xdf\x3e\x58\x7f\xb1\xfe\x72\xfd\xd5\x6b\x6f\x49\xbc\xb4\x2a\xf8\xf2\x3e\x56\xb0\xe9\xcb\xb1\xcf\x07\x0b\x76\xcb\x6b\x14\xd1\x89\x0d\x3f\xf7\x6d\x81\x1c\xfc\xf9\x9c\x61\xaf\x97\xce\xde\x53\x88\x2a\x5c\xc8\xec\x5a\x14\x55\xc2\xe0\x3a\x0a\x2c\x99\xd7\x15\x61\x13\x9b\x03\x2f\x13\x97\x80\x79\xe4\x12\x13\xf2\x3e\x84\x7b\xce\x4d\xb4\x01\x67\x67\x83\x43\xf4\x3c\x0e\x7a\xf1\xc9\x48\xde\xdb\x3b\xc4\x46\xf6\x0e\xef\x31\x72\x5e\x83\xe2\x22\x2e\xe1\x0a\x55\xec\x95\x7f\x12\xa4\xb2\x22\xdc\x06\x28\x88\x1e\x0a\x69\x1b\x42\x4e\x58\x00\xd9\x46\x8d\x96\x67\x7a\x5b\x3c\x56\x20\xf3\x49\xe2\x1f\xe1\xaf\xe3\x1a\x5d\x17\xb5\x05\x63\x57\x97\x84\x3d\xa7\xea\xb1\xe4\x84\x72\x3e\xf1\xb5\xcd\x54\xdb\x2d\x94\x29\xe4\x5a\x02\x3c\xa9\x8d\x68\x40\x95\xfb\x27\xaf\x98\xcd\xe1\xad\xc3\xb5\xa5\xb8\x64\xde\x45\x26\x2c\xbe\x9c\x77\x9e\x09\xcd\xd3\xf1\x80\xb6\x57\x8c\x3d\xef\xea\x00\x7d\xac\xd1\xc5\xb5\xe5\xcb\x21\xaa\xa2\xe6\x82\x96\x6a\x60\xbc\xcc\xbb\x44\xd4\x99\x82\x28\x8a\x4b\x83\x45\xa3\x07\xfa\x6b\xf1\xb8\x70\xaa\x73\x5e\xb2\x93\x9f\x7e\xf3\x9d\xf1\x12\xf6\x4a\x75\x65\x2f\x79\xa4\x65\x1e\xb8\xba\x85\xcd\x40\x0e\x47\x73\x4e\x5b\x66\xee\xe2\x6b\x3c\xc9\x9f\xa0\xf7\x91\xf3\x1a\xfa\xf2\x8a\x52\x1b\x44\x63\x88\x55\x5f\x8e\x10\x29\x78\x41\xbf\xf8\xe6\x23\x1c\x76\xbf\x5b\x3b\xca\x4d\x9f\x94\x38\x89\xdb\x91\x5d\x7b\x67\x71\xe7\x0e\xd1\x0b\x11\xdd\x23\xa9\x5d\x2a\x77\xfd\x86\x0e\xce\x5e\x68\x67\x74\x70\x8a\x88\x61\xbc\xe3\xbb\xe4\x7e\x23\xfa\x62\x07\x9d\x11\x2a\xc0\x18\x30\x89\x6d\xa4\xa2\xf0\xb6\x87\xea\xc1\x4b\x18\x35\x22\xa6\xb6\xd5\xbb\x8c\xde\xe5\x21\x45\xe6\x91\xfc\x71\xb8\x48\x8a\x45\x12\xa4\x94\x75\x81\x14\x0b\x24\x28\x4b\x09\xaf\x3d\x20\xec\x58\x87\x9a\x26\xf2\x0d\xac\x09\xc6\x3c\x2b\xf6\x5d\xaf\x2a\x5a\x9b\x91\xc2\x89\x29\x25\x9e\x94\xa6\xc7\x9e\x1c\xd4\x83\xc5\xcc\x87\xb1\x78\x54\x58\x6b\x95\xc5\x3e\x4a\x5d\x96\x38\xfb\x11\xaa\x15\x1d\xf3\x29\x42\x74\xbc\x81\x89\x86\xeb\xd9\x2d\xe4\x42\x65\xf6\x0b\x0a\x13\xf9\x1a\x95\x29\x71\x02\x6d\xb7\x85\xb9\xd7\xa1\x90\x9d\x16\xa2\x9e\x00\x56\x64\x71\x2e\x26\x93\xd8\x92\xc7\x86\x54\x5f\x1e\xa1\x02\xc7\x89\x18\x3d\xec\x88\x67\xbe\xc4\xee\x28\x7e\x8c\x0b\x7b\x5a\x7e\x1f\xd7\x0d\xfc\xfb\xd8\x51\xb1\x60\xb1\x34\xc6\xfc\x3c\xad\xb9\xbe\xd0\x37\xad\xd1\x3e\xc9\xb7\x79\xce\xb4\x27\x9d\x75\xc0\x91\x16\x9d\x70\x31\x50\xd2\xd4\x50\xc4\x2b\x4b\x74\x12\x9a\xcd\x6c\x45\xbe\x31\x72\x08\xe6\x63\x64\x79\x8d\x1f\xc9\x4c\x98\xb7\xfa\x3b\xbf\xe0\x35\xdd\xde\xc1\x6c\xd8\x7b\x81\xf8\xeb\x4b\x22\xb3\xc9\x72\x9a\x0c\x52\x5d\xf1\xd6\x97\x97\x78\x16\x9e\xd3\x2f\x9e\x85\xef\x6a\x6a\x0a\x30\x42\x7a\xa0\xb5\xa9\x8f\x82\x82\xba\x08\x07\xb0\xe4\xe0\x85\x09\x69\x7a\x00\x22\xe6\xcb\x2d\xac\xf6\x0e\xfd\x62\xb5\x4f\x4b\xd5\x9a\xee\xbd\x0f\x1c\x76\x08\xc2\xdd\x82\xc2\xef\x6f\x35\x96\x40\x8d\xe0\x5b\xca\xbd\x05\x9b\xff\xfb\x4a\x13\x45\x05\x0d\xb4\xb7\xda\x0d\x30\x94\x50\x22\xd9\x1b\x84\x21\x48\x31\xb0\x50\x9d\xba\x45\x37\x58\x94\xcb\x1e\x8a\x45\x31\xdc\x50\x9d\x07\xf8\xae\xb3\xb8\x88\x76\xde\xde\x36\xd4\xba\xed\x1a\x01\x8e\x0c\x04\x99\x3c\xb3\x85\x9a\xc8\xd2\xa9\x63\x3a\xd2\x2b\x43\x83\x87\x0b\x67\x1c\x15\x32\x22\x85\x93\xeb\x64\x44\x6e\x17\xf6\x05\x1a\xf9\x52\x80\xc8\x36\x8a\xb8\x53\x79\x14\x39\x9f\x7c\x20\xc2\x29\xf5\xca\x27\x30\x17\xa6\x72\x1d\x08\xb5\x40\xe0\x97\x98\x1e\xc2\x00\x20\xa1\x2b\xfc\x9b\xdb\xa0\xc0\x93\x2a\x42\x36\xb7\x84\xb6\x66\xae\x48\x6b\x8b\x52\x06\x14\x1a\x8c\x2b\xc3\x2c\x45\x79\xaa\xd3\x69\x85\x13\x40\xfa\x46\xc2\xff\xac\x00\xd2\x46\xf5\xa7\x1b\xa0\xc1\xb3\xd1\x3b\x22\xcd\x10\x9f\x9d\x18\xa5\xdd\xd4\xf2\xb7\xe8\x19\x8f\x8f\xd7\xa8\x91\xef\x8a\xde\xb4\xd1\x74\x97\xbc\xb6\x19\xff\x75\xd5\xc6\x69\x77\x17\x55\x8a\x71\x42\x86\xa9\x7c\x19\x39\x43\x9e\xe5\x11\x3d\x8c\x78\x96\x07\x35\x4b\x5e\xa7\x56\xa4\x8c\x73\x76\x97\x73\x6f\x91\x6c\x44\x86\x9a\x8e\xe4\xcb\x8f\xa9\x5a\xbd\xb1\xda\xca\x34\x8c\xb6\x0c\x29\x36\xbb\xe2\x18\x16\xde\xbe\xa7\x0d\xf1\x8c\xe0\xfc\x35\x90\x58\x47\x4c\x09\xc0\xc5\x28\xfa\x33\xd6\xe8\x25\x41\x4d\x3d\xf7\x0a\x4a\x1d\x00\x98\xe9\xa7\xa5\xc0\x0b\x13\xf9\x58\x83\xd0\xc7\xac\x80\x11\x90\x35\x1d\x74\xe6\xac\x66\xe0\x41\xae\x7c\x43\xfd\xf6\x48\x03\x6e\x9a\x2b\xbc\x82\x7d\x7b\xc8\x5e\xf0\xc8\xaf\x09\x36\x05\xbf\xe2\x25\xda\x2a\x18\xee\x90\x2b\x4e\x66\x8d\x69\xb2\x39\x6d\x54\x27\xb3\x47\x85\x5a\x2d\x99\x1e\x15\xa0\x54\x67\x80\x42\x00\x8a\x43\x89\x2d\x57\x1c\x4c\x3f\xd3\xeb\xb8\x40\x6d\xe4\x17\xb8\xe2\xb0\xb6\x6f\x76\x46\xb5\x23\xd7\x53\x79\x88\x40\xf3\x82\x7e\xf1\x08\x9f\xa7\x72\x27\x72\x1e\xbb\x62\x8d\x12\x9f\x5c\xb1\x3d\xbd\x4d\x5a\x86\xd5\xb2\xe5\x9b\x01\x2c\x3b\x50\xb2\x80\xca\xcd\x54\xbf\xb4\xf5\x36\x9f\x5f\x77\x18\x59\x05\xbc\xe7\x30\x94\xd5\x1a\x66\xe8\x74\xcf\xbf\x46\x36\x8a\x8a\x38\xfb\x32\x95\x97\xb5\x5d\xa8\xf3\x8d\x49\x1c\xa9\x6b\xb1\x99\x4a\xdf\xb9\x77\x71\xcf\x9d\x4c\x52\x1f\xfd\x50\x02\xd9\xea\xd6\x5d\xc9\x05\x95\xda\x6b\x0f\x68\x90\x54\x66\x45\xac\x45\xf9\xc8\x28\x38\x14\x2c\x2a\x44\xe2\x65\xa1\xe8\x0b\xb8\x2d\x90\xb6\x55\x6e\x05\x49\x23\x00\xa9\x76\x27\x0f\xe6\x15\xa1\x47\x53\xd4\x7c\xf1\x59\xbd\xd5\x23\x57\x86\xd7\xf0\x23\x36\x52\xd9\xab\x02\x16\x53\xee\xc4\x28\x7a\x6f\x29\x2d\x05\x57\x6c\xa5\x53\x6e\x2f\x34\x41\x2a\xa1\xdc\x81\xa7\xbd\x3f\xf5\x01\x04\x6c\xa4\x46\x48\x98\xd1\x52\x3f\x4e\xe5\x01\xe3\xbd\x9f\x28\xb5\x81\x18\x70\x2a\x2f\x22\x67\x15\xe0\xd2\x2a\xa5\x5e\x40\xea\x45\x2a\xcf\x39\xdf\x47\x4a\x61\xbe\x37\xa9\xec\xd7\x21\xb5\x39\x78\xbd\xbd\x63\xe3\xa2\xa6\xe2\x64\x52\x67\x6e\xa2\xec\x13\xba\xe4\x35\xd1\x63\xcf\x81\x7d\x9f\x15\x74\xaf\xbd\x28\x11\x4f\x52\xb9\xc6\xa7\xe1\x11\xa5\x00\x4b\xa3\xc9\x7d\x02\x9d\xfd\xe1\x36\x20\x96\xe3\x22\xd6\x59\x8b\xa1\x4b\x0d\x35\xbc\x94\xb0\x10\xa8\xf2\x45\x6c\xd6\x97\xfc\x76\x02\xae\xc1\x0e\x1c\xf1\x14\x31\xa8\x4a\x6c\xd8\x7c\xdf\x64\x27\x07\x9c\x85\x25\xcf\x6d\xd5\xf5\xf3\x35\x2e\xcf\xe9\xf4\x33\xac\x75\x10\xaf\xae\x6b\x4d\x4d\xa0\xd5\x2e\x35\x53\xea\x82\xeb\x51\x5f\xcd\x59\x7f\x97\xca\xe3\xa9\xdb\x0f\x41\x71\x16\xbf\x88\xcf\xb5\x86\x94\xc8\x9a\x18\x37\x76\xaa\x02\x55\x60\x14\xa8\x3c\xda\xa9\x6f\x67\xd5\x4e\x75\x35\x16\x59\xba\x5e\x6a\x08\xca\x3e\x4f\xe5\x36\xae\xe1\x77\xf4\x8b\xce\xab\xbe\x9e\x97\x07\xbe\xf3\x24\x6b\x36\x96\xbe\x66\x27\x9e\xb1\xac\xaf\xbb\xde\xb1\x22\xa0\xd8\x1e\x87\x08\x6f\x92\x9e\xa7\x4f\x5c\x6d\xd6\xfe\x01\x80\xf5\x29\x17\xc4\xb5\xbf\xf2\xda\x84\x61\xd2\x51\xff\x70\xf3\x28\x0e\xa6\x8d\xe2\xce\xcd\x65\xe7\x94\x7e\xc1\x6d\xa6\x15\xab\x7c\x5a\xb3\x29\x90\x31\x60\x64\x1d\xfa\x88\x07\x16\x1b\x4b\x7d\x3c\x57\xd1\xff\xf0\xb2\xdf\x40\x37\x02\xd7\x88\x45\x4f\xdf\x65\x36\xc5\xad\x91\xf8\xc8\x44\xa6\x07\x94\xfa\x73\x8b\xe2\x25\xc9\x45\xbf\x4f\xe5\x49\xe4\x8c\x71\x25\xc6\x98\xea\x11\xc9\x6d\xf0\x6c\x9b\x74\xb7\x18\xcf\x96\xd6\x05\xea\xd4\x47\x76\xe0\x43\x5b\x23\xc3\x82\x3c\xf2\x52\xbc\x9f\x51\xea\xfd\x94\x52\xef\xc5\x73\x5b\xc8\xd6\xe8\x07\xc3\x20\x0b\x1a\xfb\xf2\xbb\xac\xf0\x05\x11\x26\xf9\xa1\xf4\xee\x18\x10\xe7\x3b\xa5\x77\x40\x6f\xcb\xa7\x99\x78\x6f\xbf\x43\xc8\x2c\xbf\xcf\x84\x36\xef\x94\xcf\x91\x40\xf2\x07\x59\x90\xc8\x30\xc4\x64\x72\x29\x63\x4a\x10\x53\x53\x6e\xa4\x98\xce\x24\x7a\x61\x6b\x1d\x06\x80\x15\x05\xd2\xc7\xef\x87\x61\xd4\x97\xfd\x54\xa5\x56\x61\xcb\x9f\xe9\x87\xe7\xc1\xa5\x3c\xc1\x07\x1d\x5e\x40\x0e\x62\x11\xb0\xcc\x51\xae\x26\x94\x1c\x47\x9f\x64\x4a\xc9\xf8\x64\xe4\xf7\x32\x39\xe6\x07\x26\xc2\x81\x04\xa7\xa7\x71\x94\x3d\xba\x94\x01\xd5\x45\xfc\x2b\xf9\x02\xdb\xee\x8d\x13\xe8\xe6\x51\xaa\x93\xe4\x9e\x5f\x5e\xe2\x73\x3f\x38\x84\x52\x3d\x00\x9b\xa1\xc8\x65\x21\x72\x8b\xbf\x0d\x60\x98\x07\x9c\x1c\xfa\x97\xf2\x90\x92\x21\x72\xe2\x03\x2c\xf3\xce\xc7\xe7\x24\x1e\xc9\x5e\xa2\x52\x5c\xf5\xb0\xf0\xf8\x0e\xf5\xea\xe4\x48\xbf\xe3\xc7\x01\x3e\x0e\x42\x98\x87\x63\x95\xc2\x39\x7d\x4b\xe9\xa1\x9f\x65\x41\x24\xcf\xac\x87\xc7\x41\x30\x92\x27\xfc\x22\x3e\x97\xeb\xa9\x4a\x71\x7b\x17\xf4\x18\x27\xeb\xb0\x46\x32\xb4\x1e\xf8\x73\xac\xde\x6c\x44\xf2\x95\x49\xf2\xa7\x55\xf5\xbc\x79\x1e\xc9\x17\x79\x9a\x3f\x7e\xa4\x17\xea\x9c\xa4\xf2\x23\x4e\xd1\x51\x12\x8f\x47\x30\xc9\x3e\x7e\x23\x2d\x04\x78\x48\xf9\x21\xcc\x42\x7f\x28\x2f\x13\x7a\xc8\xd0\x37\x0f\x95\x94\x07\xfc\xe6\x2c\x48\x32\xf9\x28\xe4\x74\xfc\x29\x90\x63\x2c\x86\x9c\x65\xf9\x46\xa7\x36\xd0\xcb\x30\xa4\x4f\xfc\x91\xfc\x90\x70\xe2\x39\xe6\x78\x92\xf2\xc3\x5b\xc4\x69\x52\xf9\x88\x1f\x01\x7a\xc0\xc3\x49\x9c\x3f\x68\xf9\x85\x3c\xa2\x97\xc1\x49\x1c\xfe\x00\x2d\x51\x9d\x41\x72\x14\xc8\x67\x54\x32\xc8\x8e\xe3\xbe\x7c\x9f\xa7\x37\x07\xf2\x5b\x7a\x0a\x2f\x60\xd7\x5d\x62\xe1\x28\x38\xc2\x2d\xd4\xc3\xb2\xf1\x49\x98\xc9\x1f\x30\x43\x8c\x2b\x3f\xc4\x77\x23\x3f\x04\x32\xf5\x07\x4e\x26\x34\xf6\xf3\x34\x7f\xe0\x39\x5c\x33\x6f\x68\x2a\x7a\xf4\x18\xc2\x1e\x3f\xa5\xd4\x70\x0c\xc9\x3b\x14\x0d\x4e\x77\x7c\x3d\xb6\x9e\xa0\x5b\x17\xf4\x8c\x97\xc4\x45\xa2\x52\xab\x99\xfc\x0e\xf7\x5e\xe2\x47\x30\xa2\x73\xcc\x00\xdb\x3d\x39\x92\xdb\x29\x25\x91\x73\x28\x9f\x26\x94\x3e\x89\xcf\x20\x0b\xa7\x53\xe8\x8f\x4e\x6d\xf9\x89\x7f\x02\xd0\x51\xf0\xc9\x7f\x47\x89\xe3\xf1\x60\x00\x9b\xf3\x5b\xcc\x44\x30\x5d\x6e\x27\x8a\x23\x82\x07\x2b\x34\x69\x3c\xc0\x83\xd4\x3c\x6e\x26\x18\x8b\x2c\xa2\xef\x23\xe8\x4a\x5f\x0e\x30\x8d\xb1\x30\xe4\x4e\xa2\x52\x3c\x21\x2f\x0b\x8f\x7c\x18\x36\xf5\x3b\x7e\x7c\xcd\x8f\x23\xf9\x82\x12\xc7\x00\x8e\x32\x78\x7d\x1c\xf2\xd3\x58\x7e\xa4\xf7\x21\xf2\xb4\xd7\x70\xf0\x59\x4c\xc2\x0d\xf9\x8a\x72\xc4\x5b\x43\x80\x1c\xcc\x3f\x95\xab\xf4\x0a\x26\x2a\x85\x9d\x7d\x22\xdf\xe2\xe3\x38\xc2\xa5\x78\xea\x73\xf2\x54\x6e\x24\x94\xfa\x21\x1c\xc9\x2d\x93\x7c\x17\x02\x85\xfa\x18\x1f\xcf\x78\xcb\x3d\x0f\x4d\x1a\x76\xe9\x77\xf8\x74\x7e\x0c\x90\x40\x26\x94\x84\xec\xf1\x38\x93\xef\xb1\x56\xd4\x51\x90\x7d\x7c\x7d\x01\x90\xfa\x13\x56\x82\x95\x7f\xeb\x73\x42\x75\xed\x95\x7a\x4f\x2d\x7d\x8f\xdf\x10\xf8\xd1\xf9\xa6\x03\xdd\x8b\x87\x43\xcc\xf7\x41\xc3\xbd\x38\x0d\xf8\x4b\x60\xce\x79\x50\x3c\xe4\x01\x8a\xda\xfa\x0c\x85\xd1\x39\x0c\xec\xdf\x80\xa1\x29\xef\x72\x75\x88\x63\xab\x03\x69\x40\x8d\xbc\xe5\x39\x0f\x87\xbc\x43\x70\x5e\xc6\x01\xce\xcc\x65\x0c\xd4\x63\x40\x4a\x0d\xfd\xbe\xdc\x89\x09\xbe\x23\x8f\x1e\x76\x18\x03\xed\x93\x60\x88\x88\x80\x7c\xc7\x8f\xa3\x30\xf3\x87\x78\xe8\x9e\x12\xec\x45\x9f\xd4\xf2\xcc\x24\x19\x90\x31\xb0\x3d\x04\x60\x2c\xdf\x63\x1a\x3a\x9d\xd2\x34\x7c\x4b\x4f\xc4\xef\x97\xdf\xe7\x69\x96\x10\xcb\x0c\x5b\x47\xaf\x5f\x97\xf2\x1d\x43\x4d\x18\x6c\x94\xaa\x14\xab\x55\xbd\xf5\xd5\x23\x5e\x2b\x8f\xf5\xb7\x17\x3e\xec\xfd\xc4\x7e\xe2\xdc\xcf\x7d\xeb\x15\x96\xf8\xa4\xf3\xbc\xa3\xb5\x7d\xce\xcd\x24\x50\xba\x8f\x49\xbc\x4c\xdf\x60\xbf\xf0\x06\x7d\x42\xb0\xac\x1f\x44\x70\xb8\x2f\xe5\x59\x4c\x90\xad\x37\x1c\xf7\x61\xb7\x7c\x97\x08\x13\xe5\x46\x1e\xf1\xc3\x36\x1d\xd7\x0f\x54\x0a\xd5\x4d\x58\x30\x24\x8f\xf4\x0b\xdc\xc2\x3b\xb4\x74\xe9\x23\xb6\x69\x90\x97\xfc\x0d\xc5\xec\xf2\x80\xd3\xca\x90\x58\x1e\xaa\x47\x58\x09\x00\x1a\xea\xe1\x74\x0c\x50\xe8\x42\x3d\xa0\xe8\x5c\x9e\xf3\x03\xcb\xdf\xe4\x4b\xae\x5e\x4b\xe8\xe5\x26\x3f\xbf\x44\xe0\x29\xb7\x39\xeb\x2b\xff\x95\xdc\xd1\xc9\x2c\x3c\x43\xd1\x28\x3f\x21\x10\xda\xd4\x69\xa4\x73\xe5\x6b\x7e\x52\x3b\x7a\x8d\x9f\xec\xf3\xf7\x9a\x1b\x50\x0b\xb8\xc1\x19\x58\x36\x2e\xb7\xf8\x09\xa9\xec\x3e\x8f\xfe\x31\xbf\x79\xa3\x2d\x50\xe4\xa7\x90\x2e\x86\x43\xff\x90\xb6\xd8\x5b\xac\x0d\x55\xdc\xe4\x61\xa2\x52\x4a\xd9\x4d\xae\xf3\x6d\x71\x21\xbf\x67\x30\x0e\xa4\xee\x18\x81\x78\xbc\x16\x47\x03\x00\x65\x99\x3c\x20\xa0\x1e\xc3\x75\x7d\xc8\xa9\x73\x79\xcc\xd0\xb9\x2f\x83\x98\x13\x2f\x82\x41\x26\x9f\xab\xb7\x7c\xb0\xbe\x53\x10\x9c\xa4\x95\x32\x8a\x19\xee\xa2\xc4\xeb\x4e\x48\xb0\xb4\x3f\xc6\x1b\x21\x35\x69\x2e\x36\xe2\x17\x23\x40\x43\x64\xc2\x10\x3a\x05\xdc\x42\x9e\x52\xa1\x71\xb4\x11\x41\xc7\x32\x38\xb0\x72\x0d\x4f\x21\x1e\x98\xef\xe9\x3c\x46\x00\x07\x69\xb0\x1f\x18\xbe\x9e\x00\xe5\xac\x01\x6f\xa0\x36\xf9\x07\xdf\xbc\xc8\xf7\xf2\x1d\x7a\x89\xf1\x85\xa8\xf8\x9d\x54\x3f\xf2\xd1\x0a\xb1\x13\xe9\xf8\x44\xbe\x24\x90\xa9\xa4\x6c\x32\xa6\xa7\x24\x3c\x01\x7a\x43\xa5\x68\x12\x52\xfd\xc4\xc3\x19\xf3\x23\xec\x1b\xd9\x8b\x09\x40\xa8\x53\x3a\x8c\x0d\xb8\xd8\xe8\xcb\x6d\x7c\x3a\x8f\x13\x64\xcd\x11\xa8\x80\x1d\x43\x47\xd5\x8f\x2e\x79\x18\xe8\x13\x19\xb6\x87\x3a\x21\x7d\xc0\x59\x61\x69\xf8\x0c\xc7\xc3\xfe\x90\x27\x12\x93\x09\x4f\xe1\x31\xde\x26\xfd\x24\x3f\x5b\xfa\x68\xd1\xf6\x82\xdc\x04\xa0\x2a\x12\x8b\x3c\x6c\x44\x31\x52\x2c\xc9\x2c\x2c\xec\x9d\xac\xd7\x1c\x0a\xf0\x40\xac\xab\x0c\x65\x10\x68\x24\x04\x73\xe5\xc3\x14\x05\xf2\xbd\xba\x9d\x35\x9a\xcc\x6f\x6b\xf8\x36\x45\x05\x36\xed\x08\x35\xeb\xd6\xb8\x31\xcc\xc9\x90\xf7\x09\x19\xce\x5d\xbb\xde\xfb\xa4\xe0\x19\xd2\xbd\x86\x66\xdf\xae\x6f\xef\x6c\x6c\xc2\x71\x14\x41\xe0\xec\x36\x10\x5b\x6e\x88\x86\x42\x9a\x21\x45\xe8\xac\xfe\xe5\xa8\x53\xa2\xa1\xf0\x8f\x3c\xc5\x1f\xf6\x0b\x1c\xe7\x60\x37\xdb\x2f\xc6\x3d\x47\x96\x3d\x36\x62\x70\x54\xa8\x80\xd1\x52\x48\x00\xe6\x05\x7f\xcd\x15\x5d\xa8\x2c\x37\x45\x09\xe6\xe5\x0f\xc8\xfc\x94\xf2\x51\xc7\xa2\x5b\xa0\x29\x9b\x10\x36\x51\x24\xd5\x84\x71\x23\xe4\x78\xd1\x97\xf1\xc2\x42\xd2\xb5\x1c\x45\xb2\x13\x48\x15\xd9\x00\xc3\x6c\x42\x01\x7d\xb3\xa5\x38\xcb\x4e\xe9\x0d\x79\x15\xd5\xfa\x58\x4a\xe9\xaf\x0f\xa5\xbd\xf9\xb6\x20\x0a\x01\xbd\x92\x92\x9f\x34\xf8\x55\xc5\x3c\x0a\x75\x46\x21\x2a\x87\x21\x60\x7a\x18\xaf\x1b\x3b\xee\xe1\xa4\xf8\x85\x2e\xa2\x0c\x2e\x12\xfe\xb5\x3d\x5b\x6a\x66\xa6\x4c\x4a\xd6\x6c\xf0\x9c\x4d\x9d\x92\x5c\xc9\xb1\x32\x21\xa4\x19\x3a\x1f\xf0\x1e\x32\x2b\xe3\x14\xa7\x85\xfd\x10\xe4\x0a\x79\x67\xbe\xf3\x6d\x4c\xce\xd8\xc8\x55\x4d\xe2\x06\xdd\x10\xaa\xc5\x3e\xae\xe1\x0c\xc0\x28\x4e\x7c\xa7\xf4\x0a\x59\x11\x87\x09\xbd\xb5\x66\xd3\x6d\xd1\x84\x48\x76\x41\xaf\xd6\x0d\xf3\x9c\x85\xc1\x39\xcf\xbf\xf5\x44\x73\xaf\xcc\x6c\xaf\x10\xa4\x79\x11\xcf\x63\xd6\xa4\x6c\xfd\x30\x39\x38\x78\xb8\xd4\x6d\xa8\x00\x69\x28\xac\xb4\x3c\xba\x8a\xc2\x04\x35\x55\xae\x5a\xed\x51\x1a\xbe\x71\x00\x0a\xb3\x09\xdf\x2c\x87\xa0\xb5\x35\xa9\x9d\x2b\x6b\xd9\x01\xa5\x0a\xa3\x7d\xfa\x6a\x55\xa9\x17\x9c\x90\x01\x58\x71\xbc\x7b\xa6\xac\x38\xef\x86\xa6\x13\xd8\x03\x9d\xba\xfa\x85\x2e\x60\xc3\x6d\x13\x9b\x1c\x63\xc9\xeb\x76\x15\x79\x05\x2d\x23\xf6\x3e\xad\x65\xda\x8e\xd4\x32\x34\xca\x8d\x7f\x56\xcb\xa6\x39\xa2\x4c\xa0\x31\x42\x71\xa7\x1d\xf7\xae\x06\x10\x1e\x03\x08\x38\xfa\xdd\x8f\x81\xb7\x1e\x4f\x3f\xfd\x95\x36\x59\xf8\x7c\x5d\x66\x74\x30\x95\x5f\xdf\x55\x45\x2d\x3b\x67\x71\x71\xa5\x35\xe5\x53\xbf\xc0\xf2\x23\xf3\xb7\xda\xca\xd3\xac\xaa\xa4\xba\xb9\xe6\x33\x14\x95\x95\xaa\x66\x6a\xa8\xc4\xd5\x32\x96\xd6\x4b\x1e\xe9\x76\x6a\x47\x83\xe4\xa8\x97\x9b\x5d\x5a\xc9\xba\x4a\xb7\xd9\x10\x3d\xce\x22\xc6\x4e\x66\x76\xbc\x3e\xd7\x38\x0b\x02\xbd\xe2\x6f\x2b\x0e\x20\x6b\xd9\xa2\x6b\xb3\x28\x67\x25\x38\x8b\x81\xeb\x45\x54\x13\x29\xd0\xa2\x8c\xba\xd0\x4d\x4d\x09\x4d\x99\x38\x6a\x69\x09\x86\x06\x97\xa2\x55\xac\xe0\x61\x52\x03\x23\x92\x55\xa1\x15\xa4\x96\x33\xdd\xfb\xad\xd3\xf5\x78\xd6\x26\xb0\xdc\x13\x9e\x6d\x77\x42\xe7\xea\x8e\xd2\x44\x8a\x50\x0d\x40\xe5\x84\x83\x32\xc1\x63\xe2\xe6\x1f\x6d\x9d\x17\x14\xb5\x56\xb4\xc0\x73\x7d\x29\xbf\xa4\x11\x8e\x36\xe3\x65\x47\xbd\x63\x39\x3f\x3f\xc5\xe3\xb0\xe8\xc9\x42\x70\xe4\xf7\x62\x28\xc9\xff\xd5\x48\xf6\xc8\x0f\x75\xea\x76\x46\x64\x19\x5c\xc3\x9f\x1e\x2e\x2c\xb4\xe7\xe5\x30\x77\x5e\xdc\x93\x23\xe3\xf6\x7c\x40\xf1\x6e\xc7\x38\x37\x85\x78\x62\x83\xae\xf2\xb5\x85\x11\x6c\x75\x5c\x80\xc2\x95\x4e\xc5\x8f\x0b\xa7\x81\xa7\x16\x1d\x72\x97\x55\xca\xd1\xf9\xa0\xd0\x41\xf6\xd0\x08\x80\xb8\xff\x2a\xa4\x29\x10\xd8\xdd\xd4\xb3\xee\x49\x71\x66\x7c\xb7\xf5\x51\xe1\x46\x45\x3b\x73\xc6\x93\xc9\x59\x31\xd6\x0f\x95\x3f\x91\x85\xb7\x00\xc6\x0b\xcf\x04\xc8\x4f\x6c\x95\x79\x20\xb9\x49\x67\x1e\x63\xb9\x6a\x6d\xf9\x20\x07\xde\xec\xcd\xf9\x2c\x8f\xa6\x3b\x97\x63\x3d\xc7\x70\xbc\x35\x58\x61\xe7\xe2\x00\x57\xd0\x24\x0d\x31\x14\xba\x3d\xb1\x1d\x02\x6c\x84\x90\x40\x2a\x3d\x0e\x07\x98\x0b\x51\x5c\xfc\x21\x65\x4f\x95\xc0\x17\xe3\x88\x73\xec\x57\xa4\xe8\x91\x74\x68\xf7\xa9\xba\x26\x54\xc2\x6c\xc0\xcc\xed\x3e\x8a\xbd\x37\x31\xde\x18\x00\xad\x28\x27\x36\x3e\xc1\x86\x26\xaa\x56\x3b\x37\x80\xf2\x11\x40\x37\x1c\x47\x43\xa8\x23\x80\x5d\x9f\x40\xc7\x27\xa6\x8d\x52\xa9\xc2\x26\xcf\x2a\x9b\xdc\x0a\x55\x61\x74\xcb\x61\x1f\x15\x77\x7b\x37\xb2\xdc\xa0\xe5\xde\xc2\xf9\xe2\x07\x6c\xb5\x0e\x97\x8c\xcc\x66\x41\x84\x12\xe7\xfc\xe7\x1c\xf3\x84\xb5\x94\x62\xd4\x52\x0a\x11\x39\xa6\xdf\xc2\xd5\x8e\x19\xe0\x6a\xa7\x8d\x91\xa8\x96\xfc\xdd\xcd\x88\xe4\x55\x62\xd3\xa5\x1a\xa0\x08\x67\x6c\xf0\x79\x05\x34\x92\x0a\x90\xa6\xdb\x7e\x11\xdc\x13\x93\x20\xc8\x4a\xc0\x9c\xae\x5e\x99\x14\x5f\xd3\x54\xc8\xb7\x59\x01\x29\x67\x5e\xf1\x9b\x22\xa6\x0e\x97\x08\xa2\x2e\x4f\x8a\x6f\x61\xc9\x80\x8c\x7b\x54\x7c\xa9\xdb\x7a\x56\x7c\xad\xb5\xb8\xe5\x0f\xa5\xec\x63\xf4\x7d\x6a\xe7\xfb\x76\x07\xb0\xf4\xa0\xdc\x4d\x20\x4b\x2b\xef\xe4\x69\xb9\x97\xcc\xe5\xb1\xdf\x01\x74\x2d\xe4\x21\x1a\xc8\x7e\x41\xb0\xb5\x48\x96\x04\x95\x5a\x18\x54\x17\x07\x84\x0c\x9e\xe2\xc0\xb1\x1e\x12\x07\x6e\x8b\x1d\xd9\xb8\xdf\xfa\xba\xb5\xd4\x10\x2f\x65\x5b\x6c\xca\x65\xf1\x5a\x3e\x10\x1b\xf2\x6b\xb1\x25\xdb\x5f\x89\xc7\xf2\xfe\xb2\xf8\x24\xbf\x7a\x20\x5e\xc9\xf6\xf2\xd7\x62\x55\x2e\x7f\xf9\x95\x78\x21\xef\x2f\x89\x8f\xb2\xd1\x6a\xb5\x1a\xe2\x8d\x6c\x7f\xb9\x24\x9e\x60\xee\x47\x72\x49\x3c\x83\x6a\x7e\x80\x6a\x4e\x65\x03\xa8\x7f\xe8\x5f\xd0\x9f\xf3\x8d\xe4\xa5\x21\xde\xa1\x29\x35\x5b\x2a\x1f\x58\xb4\xc8\xc1\x41\x43\xbc\x95\x8d\x5d\x66\x53\xcd\x19\x4e\xc9\x7e\x43\x3c\xb7\x5f\xc3\x45\x07\xaf\xbe\xcb\x5f\x29\xae\x09\xbc\xfc\x90\xbf\x44\xde\x09\xbc\xb9\x93\xbf\x21\xc6\x08\xbc\x7a\x9a\xbf\xd2\x0c\x11\x78\xfb\x3e\x7f\xfb\xd2\x1f\xc1\x8b\x6f\xf3\x17\xcc\xf5\x80\x77\xdf\xe7\xef\x98\xd1\x01\xef\xb2\x2c\x7f\xc9\xfc\x0e\x78\x19\x58\x2f\x77\x02\xcc\x16\xd9\x6f\x68\x7b\xc1\xcb\xc4\x7a\xa9\xb4\xd5\xe1\x6d\x98\x95\x86\xcb\x66\x00\xf0\x25\xb6\xbe\x90\xc6\xfa\xfd\x65\x3d\x1f\x7e\xf9\x93\x52\x66\x87\x4f\xa9\xf5\x69\x43\x6b\xcb\xc3\xfb\x71\xf1\x7d\xfb\x2b\xfd\xa1\x57\xfc\x90\x37\x32\xb4\x3e\xe4\x8a\xf7\xf0\x61\x54\xfe\xb0\x36\x04\x82\x59\xf1\x77\xe0\xfb\xa0\xf4\x3d\x6f\xeb\xb8\xf4\x25\x6f\xac\x9f\xa1\xc2\x33\x9a\x2a\xef\xa1\x71\xf8\xdd\xce\xbd\x23\x71\x46\xef\x1c\xf5\xd2\x45\x33\xf0\xbd\x26\xbc\x3f\x81\xf7\xf0\x36\xd8\x73\x5a\x5f\x74\xf7\xdc\x09\x96\xcb\xf6\x5c\x17\xbe\xee\x45\x5c\xf4\x08\xb2\x2c\x00\x1c\x87\x7e\x4d\x86\xd9\xe4\x28\x9b\x9c\x8e\xe3\x6c\xf2\xab\xfb\xdf\x4c\x7e\xf5\xcd\x57\x2e\x66\xb9\x84\x2c\xbb\x0b\x0f\x57\x1a\x77\xff\xda\x3e\x3c\x1e\x64\x92\x17\xd4\x39\xd2\x91\x7a\x5d\x71\x68\x5e\x5e\xe6\x2f\xd7\xa1\xe0\xc3\x5f\x2f\x3a\xbb\x7b\xe9\xde\xce\x7e\xb3\xeb\xfe\x7a\x05\xca\x5f\xd0\xdb\xd2\xcb\x73\x7a\x29\x4b\x6f\xd7\x70\x5c\xad\xc9\xde\x2e\x74\x70\xf7\xb7\xbb\x7b\xfb\xfb\x5f\x4c\xe0\xde\xbc\xbb\xef\xc2\x0b\xa7\x3b\xbf\xd7\x76\x77\x7f\xbb\x17\xed\xed\xed\x4f\xf6\xf6\x5a\x2e\x8c\xb1\xed\xee\xed\xdf\x13\xdb\x50\xee\xb7\x7b\xe7\x5f\xdc\xb9\x27\x76\xb0\xf3\xbf\x6d\x61\xd9\x26\x57\xe4\x2c\x76\xf7\xfa\x4d\x48\xec\xb5\xe0\xd7\xed\xba\xba\x4a\x55\xe7\x72\xa9\x4e\x17\xde\xec\xe1\xc0\x5f\x62\x55\xad\x2f\x9a\xdd\xdf\xde\xb9\xba\x76\xdc\x09\xd4\xb9\x77\x6f\x8f\x3e\x6d\x9a\xe1\xbf\xcc\x87\xff\x1a\xf3\xef\x8d\x97\xee\x2f\x2d\x2d\xe2\xcf\x57\x83\xbd\xf1\x20\x58\xc6\x07\xf8\xb9\x8f\xe5\x36\x70\x80\x7b\xce\xde\x9e\xdb\x85\xa7\x2d\x7c\xba\xb3\x77\xe5\x40\x07\xf6\xae\xf7\xbf\xc0\x3e\xee\xb5\xd4\x83\xfb\x85\xbb\x77\x0d\x99\x1e\x63\x26\x1a\xda\x27\x1c\xe5\xd2\xee\xc5\x7b\x18\xf1\x2b\x1a\xb1\xde\x31\xad\x66\x77\x2d\x97\x8e\xee\xed\x43\xe6\x55\xea\xcc\x45\x0f\x5a\xbf\xe8\x7f\x05\xff\xbf\xc6\x44\x00\xff\x07\x90\x18\xc0\x9b\x01\xbe\x19\x0c\xb0\x5b\x2f\x70\xdf\xdc\xf9\xad\x7b\x4f\x7c\xc4\x62\x77\x61\x3a\x92\xbd\xf1\xf2\xd2\xf2\xd7\xf4\xf7\x1b\x1e\xf4\x9b\xac\x7a\x99\x37\x76\x57\x17\xbf\xdf\xe3\x76\xa8\x21\x6e\x09\x9b\xc2\xf3\x0f\xdf\xfd\xc5\x1f\xf6\xb8\x55\x6a\x96\xdb\xa5\x86\x9b\x0d\x8d\x01\xa8\xb9\x04\x5a\x15\xd6\x49\x36\x9a\x59\x33\x68\x36\xdc\x09\x26\x1a\xdd\x46\x93\xfd\x44\xe0\xd7\xc9\xee\xd2\xe2\x37\x50\x90\xfc\x42\x20\xb3\xea\x09\x74\x61\xee\x9f\xf9\x67\xf7\x06\xff\xef\x9f\xe1\x2c\x0f\x06\xe5\xae\xff\x93\x7f\xf8\xe3\x3f\xf9\xb3\x7f\xf0\xd3\x8f\x3f\xfe\xf4\xe3\x9f\xfe\xf4\xe3\x5f\xff\xe9\xc7\xbf\xf1\xd3\x8f\x7f\xf3\xa7\x1f\xff\xd6\x4f\x3f\xfe\xed\x9f\x7e\xfc\x3b\x3f\xfd\xf8\x77\x7f\xfa\xf1\xef\xfd\xf4\xe3\xdf\xff\xe9\xc7\x7f\xfc\xd3\x9f\xfe\xa3\xff\xef\xc7\x1f\x1b\xe2\x51\x26\x77\x1b\x74\xfa\xa0\x19\x0b\xf0\xc0\x13\x42\x53\xf8\x21\x10\x0a\xbf\x36\xec\xd1\x8f\x0a\xde\xe0\xa3\x81\xf4\x0d\x03\x6e\x38\xad\x8e\x3d\x3f\xe4\xe5\xd1\x56\x0c\x7e\x18\xcc\x42\x82\x61\x2b\x24\x78\x7a\x20\x01\x30\x14\xff\xb2\x21\x83\x68\x1c\x20\xf3\xcb\xb2\x6e\x82\x47\x6d\xe6\x05\x49\xcd\xf6\x66\x56\x18\x31\x70\x11\x89\x34\xb6\x44\xf0\x60\x6c\xcc\x20\x9d\x03\x32\xfd\x60\x03\x2f\xf5\x2e\xef\xb9\x05\xa4\xe0\x49\x41\x6d\x24\x99\xc9\xe6\x0c\x70\xd3\x67\x14\x96\xe7\x07\x62\x46\xfe\x90\xed\xc6\x80\x0a\xc2\x8f\xcf\x3f\x29\xff\x8c\xf9\xa7\xc7\x3f\x43\xfe\x19\xf1\xcf\x80\x7f\x8e\xe1\x67\x7e\x49\xa0\x17\x41\x7a\x7e\x4e\x7f\x43\xfe\xf8\x1d\xfd\xfd\x40\x7f\xef\xd0\xdf\xa7\xf4\xf7\x3d\xfd\xfd\x96\xfe\x7e\x4f\x7f\x33\x2e\x10\xf0\x4f\xc4\x3f\x09\xd6\xcd\x1a\x63\xa7\xd4\xcf\x53\x6a\xe5\x94\x5a\x39\xe5\x56\x4e\xa9\x95\x53\x6a\xe5\x94\x87\x71\xca\xc3\x38\xe5\x61\x9c\xf2\x30\x4e\x79\x18\xa7\xd4\xec\x29\x35\x7b\xca\xcd\x9e\x72\x7b\xa7\x3c\xc0\x53\x1e\xe0\x29\x0f\xf0\xd4\x0c\xf0\x94\x46\x70\x4a\x23\x38\xa5\x11\x9c\x72\x77\x4f\x0b\xfd\x7c\x07\xfd\xd4\xae\x79\xd1\x5d\x38\xbb\xda\xf5\x96\x84\x71\xc8\x3b\xdf\xbe\x16\x6f\x21\x57\xe3\x77\x3f\x02\xee\xbe\x0a\x4b\xf2\xbb\x3f\xd5\x89\xbf\xae\x13\x7f\x43\x27\xfe\xa6\x4e\xfc\x2d\x9d\xf8\x33\x48\xf8\x98\xf8\x0f\x74\xe2\x3f\xd4\x89\xff\x48\x27\xfe\x63\x9d\xf8\x4f\x74\xe2\xef\x40\x62\x0d\x13\xff\x19\x24\x7a\x98\xf8\x97\x21\xf1\x18\x13\xff\x1d\x24\x90\x71\xfb\xbb\xbf\x0b\x89\x75\x4c\xfc\x3d\x9d\xf8\xfb\x3a\xf1\xcf\xeb\xc4\x7f\x0e\x09\xdc\xb1\xbf\xfb\x2f\x74\xe2\xbf\xd4\x89\xff\x4a\x27\xfe\x05\x48\x6c\x60\xe2\x5f\xd4\x89\x7f\xa0\x13\xff\x92\x4e\xfc\xd7\x90\x08\x31\xf1\xdf\xe8\xc4\x7f\xab\x13\xff\x58\x27\xfe\x15\x48\xbc\xc2\xc4\x7f\x0f\x09\x3c\xa6\xbf\xfb\x57\x21\xb1\x89\x89\x7f\x4d\x27\xfe\x75\x9d\xf8\x37\x74\xe2\xdf\xd4\x89\x7f\x4b\x27\xfe\x07\xf4\x62\x82\x89\xff\x51\x27\xfe\x27\x9d\xf8\x9f\x75\xe2\x7f\xd1\x89\xff\x55\x27\xfe\x6d\x48\xbc\xc1\xc4\x3f\xd4\x89\x7f\x47\x27\xfe\x5d\x9d\xf8\xdf\x20\x31\xc6\xc4\xff\xae\x13\xff\x87\x4e\xfc\x9f\x3a\xf1\xef\x41\xe2\x03\x26\xfe\x2f\x48\xe0\x59\xfc\xdd\xff\xa3\x13\x7f\x1b\xd7\x94\xa6\xec\x3f\xc5\x75\xa2\xd4\xbf\x0f\xa9\xd7\x08\x66\x7e\xf7\x7f\x13\x69\x87\xa9\x7f\x04\xa9\x34\x6d\x5c\x8b\xe7\xb8\x6f\x16\xe0\x69\x01\x4e\x7e\x07\x3e\x3d\xc4\xf4\x30\xc3\xe4\x0a\x26\x8f\x30\x79\xb7\x71\x17\x92\x88\x36\xe0\xfb\xbb\xf8\x1e\xd0\x07\x4c\xff\x35\x4a\x7f\xf3\x55\x07\xea\xfa\x8e\xea\xa2\x7a\xe0\x25\x7c\xa4\x7a\x3c\xa8\x52\x70\x3d\x1e\x54\x29\x74\x3d\x1e\x54\x2a\x54\x3d\x1e\xd4\x29\x54\x3d\x1e\xd4\x79\x2d\x3e\x60\x5d\x06\x73\xf6\xe0\xb8\xf0\xc5\x07\xa9\x6b\x71\x07\x3f\xee\xed\x41\x56\xf8\xc3\xfd\xc1\xf2\xe4\xbc\x05\x57\x75\x0f\x39\x74\x08\xe1\xf8\x5a\xc0\x79\xa3\x5f\xf5\xe2\x1b\xf5\xe2\x1b\x68\xe7\x29\x2a\x0b\xed\x6a\xab\x01\x8c\x09\x0f\xa4\x69\x64\x69\xc3\x46\xe2\xbd\x9d\x25\x80\x2c\x01\xb2\xa8\xad\x2c\x81\xf8\x16\x55\x89\x16\x16\xde\x17\xdc\xef\x5a\xd1\xe2\x51\xf9\x92\x61\x3b\xa4\xc4\xf7\x76\x85\x40\xc8\x0c\xa0\x4e\xfc\xe1\xbf\x26\x23\x3e\x88\x2c\xb0\xf2\x32\xa4\x85\xdc\x9c\xd0\xbf\xa6\x04\x3f\x8a\x20\x90\xef\xa9\x37\xad\xe0\x82\x0c\xc3\xa4\xa4\xee\x3d\x05\x32\x38\x90\xdf\x66\x93\x49\x86\x9c\x37\x22\xb5\xa1\x3f\x48\x70\x1b\xbb\x61\xf4\xc8\xf4\x3d\xe6\x20\x87\xf8\x81\x5c\x73\xdc\xce\x9f\xfc\x49\x0d\xcb\x88\x25\x96\x35\xe3\xe5\x0f\x2d\xff\xa4\xbf\xb0\x90\xa7\xbb\x68\x6f\x7d\x20\x93\x40\xf0\xbb\x1a\x13\xbe\x24\xb8\x46\x73\x6d\xea\x79\x37\x08\xba\x8e\x35\x80\x24\x70\xa9\x34\x7c\xe6\x5f\x55\xdb\xb5\x9b\xbb\x7b\x77\xed\x07\xdb\xad\x9f\xd1\x1b\x65\xe7\x25\x5d\xfe\xf1\xea\x72\xe0\x9c\x77\xf1\x4f\xed\x57\x9e\xa5\x2e\xff\xa0\xff\xc5\x6b\x71\x05\xa4\xfd\x6f\xbc\xdd\xb2\x46\xa1\xb1\x97\xb3\x82\x4d\x56\x7d\xed\x76\x33\x4f\x73\x54\x1b\x0d\x2f\x2b\xc4\xec\x2a\x7b\xde\xae\xee\x2b\x3b\x52\xc7\x4c\x85\xec\x8c\x9c\xa2\x64\xbf\x6e\x4b\xf4\x53\x77\xb9\x62\x3b\x1d\xf6\x6d\x0b\xb2\xdc\xcd\xf1\x59\xae\x92\xdd\xeb\x9e\x30\xa3\xa7\x9f\xfb\x38\x66\x97\xc9\x83\xaa\x8b\xe3\xb4\xe0\x53\x25\x51\x3e\x55\x46\x35\x2e\x55\x86\x96\xa7\x3a\xf6\x5e\x53\xa1\x74\x7b\xb5\xf4\xea\x70\x2a\x8a\x3e\xd2\x18\xfa\xd0\x20\xe8\x83\x1b\x70\xe6\x63\xc9\x67\xc7\x62\x1a\xf5\xa5\x6e\xac\xce\x64\xfe\x4c\x1e\xe7\x0f\x27\xba\x41\x34\x89\x4f\x9d\xb3\x5f\xd0\x20\xfe\x48\xfa\xce\x91\x64\xc7\x56\xb9\x2d\x33\x50\x6a\x12\x71\xc6\x82\x01\xef\x81\x3c\xaa\xb5\x0e\xe0\x45\x8a\x6d\xe3\x00\x6b\x59\xc7\xd7\x9d\xc0\x1c\xaf\x03\xde\xc8\x5f\x57\x37\x72\x7e\x4e\x2d\xd7\x24\xda\xdb\x5a\x98\x46\xa4\x30\xd1\x20\x3f\x0d\xb9\x25\x35\x86\x8d\x8d\x25\x63\xb5\xb6\x2d\x74\x8c\x02\xcf\xdb\x9a\x11\x90\x8b\x67\xab\x8f\xfe\x1f\xe4\x78\x57\x86\xea\x7d\x03\x13\xf5\xcd\x5f\xa2\x13\x6f\x1f\xdb\xe3\x7c\x7d\xd3\x6e\x5f\xd9\x4a\x97\x8f\xed\xb0\x7a\x6c\xfd\xda\x63\xdb\xab\x39\xb6\xe3\xd2\xb1\x4d\x6b\xcf\xe8\x78\xea\x19\xed\xe9\x23\x33\x36\x67\x74\x78\xc3\x19\x1d\x55\xcf\xe8\x60\xe6\x19\x3d\x96\xa3\xfc\xa1\x6f\x9f\x51\xdf\x39\xfe\xe5\xce\xa8\xb5\x37\x63\x3e\x3f\xed\xa5\xd9\xfb\x02\x85\x68\x8d\x71\x1a\xcc\xe1\xbe\x80\x95\xed\x84\xd6\x8e\x66\x43\x65\xbc\x8c\x47\x09\xec\xcc\x8b\x67\x01\x4a\xc0\x80\xfe\x54\x82\xa1\x63\xf3\xac\xf4\x6e\xea\xf5\xbc\x97\xc8\x9a\x47\x59\x6c\xed\x06\xfb\xc6\xe0\x04\xb0\x08\xe3\xa9\x75\x9f\x34\xee\x61\x7f\xa3\x11\x1a\xb3\xc1\xe1\x54\xb7\xee\x85\xd1\x80\xce\xea\x01\x0a\x24\xc7\x19\x9c\xde\x8f\x69\x03\x25\x5c\xf8\xb5\x75\x6f\x9c\x85\xc3\xf4\xde\x61\x18\xf9\xc9\xe5\x01\x29\x15\x1c\xb0\xdf\x30\xca\x66\x6c\xc2\xc8\x77\x7f\xe8\x86\x25\xcf\x22\x8e\x4f\x91\x47\x76\xfd\x7d\x19\xc2\x1f\x96\x0e\xa5\x4a\xa6\x28\x43\x8e\xb7\x1b\xe6\x0b\xda\x49\x2c\x35\x71\xb5\x05\x58\xcd\x19\x63\x3d\x27\x05\x9e\x72\xae\x27\x9e\x90\x43\xa3\x74\x8c\xea\xfa\xf9\x6b\x0c\x0e\x2a\x54\x1d\x7c\xee\x4d\xaf\xac\x8a\x44\x03\xad\xed\xe2\xcc\x1f\xee\xf4\x92\x78\x38\x44\xfb\x7a\x5e\x86\x86\xb8\x3a\x4f\xc2\x8c\x0c\xee\x31\xea\x53\x0c\x13\x75\x34\x4e\xf4\x33\x87\x9f\xb3\x50\x9a\xc2\x2a\x33\xdf\xa4\x76\x69\x4b\x1e\x67\x69\xf1\xba\x4b\x5e\x6d\xde\xdd\x0c\x16\x0e\x65\x0f\xb7\x1b\xc7\xe3\x30\x85\x7d\x7e\x49\xba\x52\x3b\xa8\x16\xf5\x79\x63\xc8\x4a\x83\xd0\x4e\x89\x5a\xbc\xfc\x5c\x2d\x3b\x8d\xab\xed\x2d\xec\xe7\xb8\x15\x8f\xb2\xb4\xb5\xf6\x62\x73\x67\x7d\xe7\xf5\xc1\xb3\x8d\xa7\xcf\xd6\xb7\xdd\x9f\x37\x82\x75\xd4\x04\xfa\x4b\xd1\xff\x66\xfb\xf6\x23\x78\x1d\x8f\x76\x46\x00\x6b\x92\x9f\xb3\x8b\xca\x23\x50\x56\x65\x8b\xed\x5c\xd6\x1e\x4c\xdd\x2b\xc1\x67\xec\x94\x47\x71\x96\xc5\x27\x7f\x9e\x1d\xa5\x6d\x4d\x1d\x9d\x76\xc0\x50\xc5\x67\x65\xe6\x19\xd1\x43\x9d\x5e\xc3\xe2\xac\xa9\xc8\x81\x75\x82\xd7\xfa\x4d\xd0\xcc\x6b\x3f\x10\xd3\x00\xa2\xd7\x5e\x46\x60\xdf\x9e\x09\xec\x4b\x73\xc2\xca\x71\xec\xec\xae\x3e\xbe\xd7\x8d\x60\xd8\xc0\xd7\x78\x0a\x7c\x8d\x19\xbe\xc6\x08\x5f\xe3\x7d\xed\x0b\xef\xe7\xc0\x57\xff\x9f\x2a\xf8\x6a\x4b\xe0\xf3\x5b\xf2\x0b\x7a\x66\xc4\x72\x73\xb0\x76\x1c\x0e\xfb\x49\x10\xfd\xa1\xe1\x27\x61\xef\xe4\x8c\xca\xc9\xee\x95\x7a\xfc\x07\x06\x8d\xd4\x35\x74\xa2\xf5\x7b\xf5\xec\x17\x05\x79\x7a\x65\xbf\x28\xf5\xe7\x0f\x07\xdb\xec\xb9\x3a\xf1\x2f\x9c\x25\xe1\xd4\xee\xb3\xc5\xcc\x2d\x77\xda\xad\x03\x43\x33\x21\xcc\xf2\x67\xa2\x93\xa5\x06\xd1\x9f\x60\x5d\xdf\x64\x70\xfd\x87\x3a\xaa\x79\x88\x3a\x12\x42\x38\x53\x5b\x99\x8b\xe2\x6c\x2e\x44\xd5\x63\x04\x8f\x41\xbf\xd5\xf8\x99\xa7\xe3\x17\x38\xba\x75\x9d\xae\x34\xf1\x8b\x75\xf8\xf7\x3e\xce\x37\x75\x17\x1a\xf8\xbd\x3a\xfb\x8b\x9e\xf0\xfa\x0d\x51\x68\xe0\xf7\xea\xec\x2f\x7d\xfe\xeb\xfa\x5b\x6d\x63\x4a\x97\x8b\x87\x1f\x4f\xf8\xfd\x5b\x71\x5c\xa2\xd6\x76\xe0\xf7\x90\x2b\xeb\x34\x12\x4c\x11\xc3\xc5\xe6\xc3\xf8\x24\x95\x53\x94\x9a\x79\xcb\x90\xa5\x81\xfe\x59\x08\xaf\xd0\x20\x26\xbd\xa7\x2d\x49\x0f\xa6\x50\x7c\x69\xb9\x00\x35\x30\x2d\xf7\x58\x26\x0a\x73\x58\x1b\xfa\x69\xea\x5c\xf5\x79\xbb\xbd\x22\x75\xa8\x0d\x55\xa8\x21\xd0\xca\x0f\x59\xe6\xa9\x77\x75\xec\x47\xfd\x61\xc0\xa7\xde\x4b\x5a\x5b\xfa\x0b\xd9\x5f\x42\xc6\x60\x18\xfb\xfd\x47\x68\xa6\xb3\x83\x7a\xd5\x76\x0e\x06\x67\x3a\xcf\x6a\xbf\x4f\xa6\x86\xfe\x90\xa7\xbe\x2e\x6b\xc0\xeb\x50\x93\x21\x8e\x82\xcd\x01\x26\x9d\xdd\x9a\x72\xf6\x2b\x9a\x80\xcd\x81\x53\xcd\xe6\xee\xbb\x64\xf1\x73\x3a\x0e\x81\x30\x17\xca\xe0\x43\x6f\x85\x9a\xfe\xd8\xb9\xf5\x8c\xbe\xc0\xe1\x06\x47\x61\xc4\x9b\x69\x73\x30\x48\x83\xda\xb1\xc4\xd1\x86\x55\xa4\x3a\x75\x38\x27\x61\x74\xb4\x33\x0a\x23\xe8\xc3\x63\x18\x3a\x5a\x75\x16\x6b\x8a\xfb\x81\x08\x53\xbb\x1e\x8a\xfb\x69\x65\xc1\x18\x33\x02\x2d\x0e\x79\x85\x00\xc2\x41\x3e\x3f\xcd\xd2\x27\x71\xb2\x8a\xe6\xd0\x6f\xd2\x20\xe1\x6f\x69\x5d\x2f\x7b\xb8\x0f\x68\xf9\xed\x8f\xcc\x0e\xbb\x16\x08\x90\xd8\xf4\x18\xbf\xa5\xf6\x6d\xa1\x3c\x3f\x14\xb6\x87\xf5\xf9\x7a\xfa\xf8\x78\x03\x2a\x6b\x31\xa7\xd1\x0f\xcf\x1a\x82\xbd\xa0\x95\xa6\xac\x50\x5d\x75\x1a\xe6\xdb\xb7\x1e\x78\xfb\xcb\xa5\x6b\x1a\xcd\x06\x2b\xab\x53\x6e\xbb\x7e\x8b\xf2\xe7\xee\xe9\xc6\xd6\xd4\xf9\xd1\xb4\x27\xcc\x42\xab\xb0\x4b\x85\xf5\xa1\xa7\xee\x6d\x0a\xa5\x9e\xbf\x2e\x1f\x92\xee\x8c\x6f\x9e\x5d\x5d\x71\x83\xde\x5b\x16\x51\x4d\xb5\xe5\x73\x55\x53\x7b\xe5\xe8\x4d\x6f\x44\xe1\x4d\x57\x61\x69\xfc\x5e\x26\xca\xd8\x89\x57\x33\x72\xad\xe3\x9c\x96\xb0\x04\x15\x94\x5e\xf4\xcb\xb7\xb1\x57\x7c\x07\x57\x9e\x97\xb5\xaa\xf7\xa0\x13\x34\x31\x7a\x4a\xdd\x1e\x40\x13\x23\x58\x0d\x5e\x6a\xb8\x91\x74\x53\xe8\xe4\x35\x8c\xc7\x69\xdd\x87\xe2\x94\x07\x53\x41\x54\xa4\x06\xa2\xd4\x32\x74\x0d\xa1\xaa\x54\xc9\xf4\xaf\x45\xfd\x9e\xf1\x8a\x7c\x3f\xd2\x02\x26\x10\xac\x67\x90\x3d\x03\x28\x07\x85\x14\xf0\x8e\x7d\xba\xa2\x67\x8d\xb1\xcb\x96\x2d\xa8\x2f\x4d\x11\xb2\x2a\x17\xda\x87\x78\x3c\x77\x32\x4e\xb3\x39\x58\x82\xb3\xb0\x1f\xcc\x05\x61\x76\x1c\x20\x57\x8f\x57\x6a\x2e\x86\x74\x34\x47\xf0\x70\x0e\x85\xa6\xf4\x36\x9d\xf3\x53\xa0\xc0\x20\xb7\xbd\x8b\xb1\x8e\x11\x5c\x7e\x1d\xee\x40\x4a\x1d\xc8\x9d\xc7\x0a\xb2\xf2\x8d\x20\xfb\xbb\x70\x38\xdc\x0e\x80\xf8\x38\x0b\x4a\x20\x21\x77\xa7\x43\x11\x9d\x51\x67\x03\x63\xd4\x14\xa7\x64\xf6\x11\x2b\x9f\x2c\xeb\x40\xf1\xcc\xcf\x4b\xf2\x03\x5b\xda\x05\x68\xb0\x50\x7d\x5b\x97\x53\x7b\xac\xce\x2a\xe7\xae\x13\x55\x5e\xc9\xa4\x0b\xdb\xbe\x7a\x0a\x55\xa0\xa5\x6c\xda\xe9\xca\xab\x2a\x7f\x01\xda\x3e\xac\xd6\xc8\x10\x04\x6e\x11\x82\x4a\x4e\x64\xdb\x0c\x06\xe6\xfd\x93\x04\x30\x17\xbd\x95\x1d\x32\xf8\xcd\x1f\x5d\x32\x0b\x31\x8b\xf4\x38\xec\xbf\x19\xf5\x0b\x20\x8e\x39\xcf\xe5\x9d\x57\x07\xbb\x68\x8e\x4b\xe7\x59\x09\x9f\xeb\xfb\xa2\x99\x3d\x85\xee\x14\x77\xcc\x4b\xb2\x6f\xb3\xc6\x85\xe1\xeb\xa6\x82\x54\x57\x35\x57\x0b\x5a\xb0\x7b\x53\xca\x69\xf1\x59\xe5\xa4\xbc\x46\x5b\x21\x3e\x2b\x87\x01\xee\xff\x13\x3f\xba\x9c\x63\x93\x79\x7d\x7a\xfa\x14\xbd\xb1\xf6\x5c\xa8\x13\x03\x55\xf8\xf0\xdf\xf4\xa7\x51\x9a\xf2\xca\x20\x8b\xeb\x7a\x55\x81\x89\xca\xb4\x6b\x00\x99\xcc\x27\x82\x7d\x9b\x2f\x5f\xc1\xcd\xef\xb8\xad\xde\x30\xcc\x8f\x43\x05\xd0\xd5\x4c\x7c\x0d\xd4\xab\xc9\x85\x9b\xc5\x7e\x53\xbd\xd7\xe7\x6e\xee\x5b\xaa\x4b\x5f\xdb\xf0\xf0\x71\x7c\x1e\x4d\xab\x2e\xc5\x79\x68\x55\x7a\xf8\xd0\xfa\x58\x1e\xe3\xb5\xa8\xdd\x73\x35\x50\xa7\xca\xaf\x31\xcd\x15\x4e\xb5\xab\x2f\xd1\xfa\xcf\x5f\x04\xe8\xfe\xb4\x39\x23\x07\x20\xf4\x16\x53\x21\x5a\xac\x66\x2d\x1f\x7b\xc4\xf6\xb9\x48\x18\x39\x56\xf6\x32\x70\x9c\xc1\x31\x15\x49\x4d\x97\x2a\xed\x74\x4a\x3b\xae\x7a\xdb\xde\xd0\x7a\x85\x58\xc6\x08\x72\x95\xfb\xf9\xf6\x75\xe0\xcd\x8d\xb1\xa0\x2b\x3b\x77\xda\x3e\x9d\xb2\x0b\x60\xbf\xea\xa6\x9e\xd5\x22\x9c\x99\x3a\x6d\x0c\x15\x6c\xa4\xd4\xb9\x71\x27\x2b\x61\x5e\xb1\x50\x0b\x46\x0f\x99\xf2\x5d\x0e\x5d\x00\xa8\xe1\x1f\xa9\x1c\x0a\x23\x48\xab\xe7\x9d\x46\x50\x40\x1b\x16\x16\x6c\x4d\x50\x67\x5a\x36\xd7\x92\x3f\x09\xf4\x97\xa6\xb5\x41\x6d\x15\x9c\xcc\x5a\xde\x22\x1a\x52\x8b\xaa\xe0\xcc\x59\x13\x73\x4b\x7c\xb9\xb2\x91\x0a\x2d\x2d\x95\x5a\x42\x6b\x2b\x51\x4f\x07\xe8\x65\xa9\x9b\x39\xc7\x15\xb3\x2e\x15\x13\xfb\x77\xe5\xe7\x9d\x98\x45\xfb\x0a\x29\x5e\xb8\xf6\xa7\x99\x64\x5d\x27\xd0\xe6\x4f\xaa\xf9\x1a\xcc\xa3\x32\x53\x15\x14\x75\xe9\xda\xb5\xd7\xa0\x48\xe4\xd0\x5d\x79\x38\x86\x2b\x25\x1f\xc2\x4e\x76\x39\x0c\xea\x68\xad\x9b\x90\x77\x11\x9f\x05\x09\xfa\x69\x79\xef\x35\x8e\xc3\x7e\x3f\x88\x1a\xe6\xd5\x07\xaf\xc1\xcb\xd6\xb8\x56\x0d\x72\x99\x52\x63\x46\xbd\xe0\xea\x3c\xec\x67\xc7\x5e\xa3\xbd\xb4\xf4\xeb\x86\x50\x4d\x5b\x9c\x67\xb7\xd9\x18\x5d\x60\x5d\x70\x52\xfb\x36\xae\x5b\x20\xa6\x4a\x57\x38\xbb\x63\xb3\x66\xb4\x02\xa1\xc4\x94\x8f\x00\x49\x90\xaa\x02\xa4\xb2\xb0\x1e\x66\x5b\x92\xfb\xd6\x51\x4c\xee\x9d\xd6\xcf\xc8\x7d\x49\x23\x82\x9b\xb9\xe1\x5a\xb6\xaf\x33\x77\x51\x81\x95\x35\xb3\x8f\xc4\xd3\x99\x5d\x5d\x95\xd3\x34\xad\x46\x1c\x98\x09\x99\x52\x4b\x1b\x5f\xe5\x34\xba\x3d\xa7\xfa\x65\xb7\xee\x25\x3a\x9b\x07\x98\xa7\xd7\x1c\x77\x15\x5a\xd9\xe0\x52\x53\xf6\xba\x1d\x87\x8e\xb2\x23\x75\x82\x29\x53\x1d\xc8\x85\xf5\xae\xef\x24\xb7\x76\x12\xc7\xd9\xb1\x59\x94\x77\xda\xbe\x8e\x5b\x0e\x66\x17\xce\xf4\x12\x54\x7b\x6a\x6d\x55\x87\xbd\x61\xcc\xac\xe9\xd0\x9a\xfd\xd9\x95\x91\xdf\xd9\x59\x55\x15\xb9\x18\x8d\x6b\x31\x0b\x1c\xd8\x4b\x31\x85\xfd\xc1\x4e\xe2\x91\xc9\x68\x69\xa5\x8c\x45\xd4\xd2\x55\xc9\xf1\x1f\x46\x7d\xea\x96\x3c\x44\xaf\xbd\x24\x3e\x83\x41\xe9\xb5\xdb\xa2\xcc\xfc\xf4\x7e\x23\x2a\x9c\x4f\xef\x6b\x41\xfc\x52\x6f\x79\x09\xd5\xb6\xda\x0f\xaa\xec\x56\xa6\xdc\xae\xb4\x90\xff\xc5\xe6\xbb\xf5\x6d\xaf\x2d\x8a\x42\x7f\x6f\x19\x30\x85\x8a\x73\x4b\x13\xc0\x42\x60\xd4\xd5\x54\xe6\xfa\x35\x40\x8e\x2f\x75\xd2\x15\x39\xee\x10\x4d\x12\xcb\x71\xd3\x42\x24\x9d\x74\x71\xec\x62\x18\x5a\x5f\x62\xf8\x74\xf8\x41\x7f\x98\x5a\x41\xa1\x13\xac\xf8\xdd\xb1\x8c\x9b\x6d\xcf\x5f\x41\xff\x98\x29\x46\x10\xcf\xa9\x66\xc8\x9c\xb4\x0a\xdd\x5d\x58\x18\xaf\x2c\x75\x43\x39\x5e\x6c\x7b\xc5\xcf\xdc\xfb\x85\x85\xf4\x61\xde\x37\x8a\x32\x9e\x36\xdb\x18\x5f\xc0\xda\x2c\x57\x15\xbd\x08\x0f\xc6\x35\x02\x54\x24\xb9\x56\xcc\xea\x2f\xab\xb3\x57\xe0\x8d\x97\x65\x53\x14\xab\x2a\x1f\xda\x3c\x85\x39\xd4\x5a\x6d\xb9\x23\x59\xf6\x1c\xa3\x1c\xcd\x96\xbf\x06\xe6\x6b\x50\x74\xf8\x1b\x69\x91\x35\xba\xd1\xa3\xc0\x89\x85\x17\x2a\x3a\x43\x4e\xdd\x25\xc5\xa0\x8a\x50\x4b\x1e\xb1\xbd\xac\x5f\x56\x12\xac\x93\xd7\x46\x0e\x56\xb7\xd4\x89\x1f\xea\x4a\x3b\x71\xb3\xe9\x32\x1f\x25\x42\x79\xfb\x64\x92\xed\x62\x62\x1f\x5a\x0b\x38\x95\x37\xa6\xa7\xe0\x3a\x6a\x1d\x1c\x04\xe9\xcb\xb8\x3f\x1e\x06\x68\x05\x12\xa1\x2b\x4b\xe2\x85\x36\xf6\x65\x62\x89\x08\xec\x0f\x6a\x01\xbe\xba\xfd\x02\xb8\x57\xd7\x55\x69\x43\x8d\xa2\x72\x45\x71\x83\xf4\x3b\xe9\xd0\xdc\x1b\x86\x87\xf7\xc2\x88\x02\x8d\x44\x46\xe4\x90\x7f\x5a\xbf\x08\x7a\x63\xac\x6b\x3d\x3a\x0b\x93\x38\x22\x23\x24\x04\x32\x11\xe0\x7c\x80\x06\xc3\x74\x5d\xa9\x68\x0f\x6d\x81\xae\xde\x0a\xb8\x87\x13\x8a\xc6\x9a\x1f\xa1\xa0\x04\xbb\xf0\x2c\x4c\xb3\x38\xb9\x24\x97\x70\x73\xca\xb9\xdc\x9c\x3f\x07\xd5\x34\x28\x8c\x24\x6f\x5e\xd9\x16\x4a\xe5\xfd\xd8\xca\x8f\xde\x4a\x4a\xca\x78\x37\x75\xd3\xfb\xcd\x03\x51\x3b\x4a\xaf\xfd\x35\x41\x8a\x1a\x55\xd8\x19\x7b\x5d\x03\x92\x50\xf3\x38\xb6\xa1\xfb\x41\x8a\x5b\x30\x74\x8d\xda\x86\x18\x8b\x9e\x5c\x12\x43\x69\xc2\x78\x0e\x57\x7a\x9d\x66\xb3\x87\xbb\x68\x2c\xc3\xdd\xde\xbe\x98\x1f\xa3\xfb\x33\x5e\x77\xf4\xba\x80\xae\xc7\xe2\xec\x49\x0c\xf0\x96\x62\x86\x24\xce\x98\x9a\x33\x51\xae\xe3\x56\x42\x6d\xb5\x94\x35\x3f\x1e\x85\x98\x56\x12\xe3\x77\xaa\x1d\x44\xdd\x21\x77\x0a\x18\x65\x58\xfa\xe8\x38\x2f\x81\xc1\x93\x53\xc4\xd4\x19\xb5\x46\x18\xb4\x2c\xc8\x6b\x65\x6e\x5d\x20\x8e\x45\x24\x76\x81\xac\xda\xd7\xae\x20\xd0\x51\x38\x77\xc7\xd4\x39\xa8\xad\x73\x70\x53\x9d\x83\x7d\xed\x1f\xa2\x5c\x34\xd3\x45\x35\x02\x73\xdc\x2d\x96\xdd\x67\x2f\xc2\x4a\x65\xa6\xc8\x8c\xc2\x03\xe9\x64\xb6\x27\x8c\xc0\x66\x72\x1a\xfb\x37\x47\xef\x3e\xbc\x14\x61\xa7\x11\x8e\x83\x2c\x19\xcb\x60\x1b\x6e\xb0\xb8\x36\x0a\x0e\x87\x95\xb9\xca\x9d\xe0\x2f\x75\xa2\x87\xc6\x07\x7e\x04\x70\xc1\xf6\x36\x90\xb4\x02\x13\xf2\x4b\xda\x0f\x93\x09\xd0\x57\x49\xcb\x16\x41\x22\x48\x68\x10\x0b\x09\xe3\x51\x62\x9c\x98\xa4\xa5\xc5\x95\x12\x7d\x69\xd7\x8b\x3d\x11\x71\x01\xb8\x47\x41\x45\xca\x0e\x7f\x03\x8e\x36\x9e\x87\x28\xc8\x1c\xcb\x24\x9e\xbc\x6e\xd0\x3b\x0c\x43\x13\x50\x4c\x12\x25\x2e\xdc\x82\x55\x78\x83\x4a\x52\x24\x10\xac\x9f\x07\x8e\x9c\x1d\xc3\xbc\x2b\x2d\x56\x4d\x94\x40\x59\xf4\x86\x20\x03\xfd\x8c\x4b\x2b\x23\x7e\x3a\x1d\xa3\x4f\xc3\x84\x1f\x78\xff\xc2\xb1\xd5\x3b\x1a\xdd\x35\xa0\x63\x85\xdd\x2b\x18\x92\xd7\x40\xef\x84\xe4\xb0\xaf\x51\x11\xce\x16\x17\xc1\xd7\x5e\x29\xbf\xc3\xea\x39\xd0\xa8\xd9\x5b\xe6\x5d\x4c\x1a\x51\x30\xa0\x25\x31\x36\x57\x76\x47\x05\x9c\xc1\xab\x34\xc5\x90\x9f\x2e\x1e\xb5\x0c\x83\x7d\x62\x14\x81\x3c\x24\xe3\xf5\x3e\xfb\x4c\xb3\xe0\x4d\xca\x78\x4e\x3e\x5b\x80\x6d\x20\x08\xa9\x51\x12\xaf\x87\xb6\x50\x56\x8b\xc8\x08\xca\x5e\xf5\xd8\x53\x9e\x12\x95\xd2\xfc\x24\x5e\xc2\x13\x65\x4b\x0f\x91\x77\xf0\x29\xc0\x86\xbd\x72\x4b\x36\x83\x4c\x55\xa7\xcb\xeb\x32\x3a\x7e\x01\x55\xf2\x0c\xd1\xd2\xcf\xac\x04\xcb\x98\x4a\xc8\xe7\x28\xf1\x8d\x5e\xc7\x95\x8a\xea\x6a\xb0\x0b\x98\x5a\x94\x6e\x36\x3a\xf0\xbb\x55\x25\x56\x7e\x53\xc7\x51\xfc\xa8\x7c\xd9\x4c\x1f\x07\x67\x2e\xdd\x20\xa1\x5a\x51\xb3\x2a\xde\x72\x1b\x56\x74\xb9\x46\xbd\x7b\xea\xa5\x60\x41\xa2\xb9\x91\xab\xd9\x89\xbb\xfb\xc8\x27\x34\x2a\xe8\x69\xc9\x45\x89\x89\x33\xe0\xb0\x2f\x6a\x74\x2f\xd4\x70\x76\x7f\x7b\xaf\xfb\xab\xfd\xa6\xdb\x70\xbd\xc6\x17\x0d\xd2\xa5\xd4\xdf\xd1\x43\x8c\x8f\x77\x73\x03\xed\xff\x29\xc7\xde\x5e\xa3\x99\x01\x1d\x30\x42\x57\x2c\x57\xec\x26\x38\x21\xd7\x39\x96\x22\x7c\x84\x1a\xec\xa2\x11\x62\xfc\x78\x3c\x99\x14\xe5\x09\x83\x87\xa9\x1e\x60\xe1\x5c\x23\xb1\x1e\x1d\x20\x5d\x03\xc6\xd7\x16\xd9\x1d\xb6\xd6\x34\x38\x65\x88\x71\xcf\x73\xd0\x16\x7c\x75\xf1\xfb\x83\x3b\xfb\x2a\xb5\xb4\xf8\x0d\x3c\x7c\xe1\x4e\x76\xbf\x68\x39\xee\x1e\x5a\x06\xec\x35\x27\x57\xd7\xbf\xbd\x83\xd6\x01\xe3\xe9\x65\xba\xfb\x5f\xec\x76\xf7\xbb\x58\x90\xed\x08\xee\xed\xe1\xbf\xee\x04\xff\xec\xdd\xa3\x1f\x78\x3f\x84\xf7\x5d\x98\x0b\x97\x0c\x07\xae\xae\xc5\x40\x5e\x85\xe9\xea\x61\x1a\x0f\xc7\x59\x1d\x43\xa2\x71\x8f\x66\x34\x77\xf6\x7e\x2d\xd0\xe1\x4d\x59\xc4\xa1\x9d\xb9\x1b\xe3\x81\xbd\x7b\x68\xa0\x0f\xa5\x31\x02\xaa\xb0\x2f\x30\x9e\xcb\x1a\x83\x1c\xdc\x15\xad\x7c\xba\x8b\xa5\xd2\x3a\xb1\x1e\x9b\x62\xa0\x6d\x8d\x5a\x47\x84\x5e\x56\x15\x02\xe3\xf4\x71\x68\xe9\x90\x7d\x20\x19\xef\x4c\x08\xd0\x94\x86\x7d\xee\x1b\x32\xd6\x8e\xb2\x4b\xb6\x03\x29\xee\x15\x7f\x37\x68\xb6\x29\x54\x10\xb2\x45\x71\x59\x6b\x3b\x06\x20\x7d\x02\x0b\xd6\xd1\x17\x5f\x65\x6a\xc6\xf9\xa6\xe6\x9b\x01\x09\xa0\x18\x70\x7b\xde\xab\xa2\xd1\xc5\x19\x8f\x15\xd7\x06\x48\x1b\x9d\xc5\x84\xec\x86\x77\x3a\xbe\x2e\x22\xd6\x6a\xa1\x1a\x2a\x1e\xb8\x0e\xd7\x8e\xa4\xd3\xdd\x97\x18\x50\x3d\x3a\x9a\x6b\xfc\x3a\x6d\xcc\xd1\xc4\x04\x70\xac\xc9\x74\x03\xaf\x20\x7a\x7f\x17\xe8\x33\xc5\xf8\xf3\x75\xdc\x0b\xee\x8b\x24\x90\x5f\xb0\xb2\x72\xa8\xc9\xae\xe3\x53\x03\xbb\x70\x97\xef\x0b\xdd\xa4\x9f\xb7\x47\xe5\xe7\x7e\x35\xf7\xeb\xb4\xdc\x56\x84\xb1\x3c\x3c\x2e\x8e\xb1\x8a\xcc\xbc\xf4\x68\xb7\x98\x55\xa7\x0b\xa9\x4e\xce\xa9\x16\x74\x98\x3b\xdf\x5f\x58\xf0\xd9\x23\xab\x83\x61\x23\xa0\x0a\xfb\x9e\xab\xdb\x69\x05\x33\xbb\x86\x2a\x50\xce\x9d\xef\xb2\x41\xf1\x92\x84\xb9\x8a\xc8\x2b\x5b\xd0\x8d\x1d\x8c\x0f\xe0\x45\x5a\xc2\xe9\x2b\x1d\x8e\x70\x80\x6e\x97\xae\x88\xf2\x7e\x12\x27\xd0\x63\xaf\x71\x08\x35\x7c\x0a\xb2\xb4\x71\x9d\x73\x9e\xba\x83\xe2\x9d\x8c\xfc\xbd\x6e\xa3\x99\x78\x95\xf7\x05\x00\x3c\x40\x00\x5c\x04\x2d\xde\x83\x6f\xc4\x69\xea\x7d\xb9\x34\x13\x6f\x5f\xae\x51\xca\xbe\x89\xc4\x51\x18\x95\x01\x61\x39\xc8\x03\x6a\xc6\xdc\x01\xca\x08\xe6\x1e\xa1\xbd\x04\xe8\x12\x07\xf5\x47\xc4\xd5\xc0\x1f\xa6\x97\x53\xef\xce\xdd\x60\xbf\x6b\xc9\x0c\x1f\x22\xec\xbd\xbb\x32\x97\xc2\xd8\x87\xac\x87\x77\xec\x9f\x05\x80\x75\x36\xee\x36\x83\xe6\xdd\x06\x89\x06\xef\xba\x9a\xd1\x2e\xe8\x9e\xf2\xc2\x96\x46\x68\x29\xce\xbd\x50\x38\x01\x07\xcc\x2b\x30\x7d\x7c\xbe\xbb\xb8\x9b\xde\xf2\xfd\x9c\x01\x22\xa6\x8e\xd9\xfb\x1a\x11\x96\xe5\x1a\x75\xd3\x1b\x68\x1e\x76\x7a\x16\x6b\x45\x53\x85\xe4\x05\x36\x92\x17\x55\xe9\xd0\xe5\x1a\xad\xb7\xea\x22\x89\x3f\x62\xf6\x7f\x4e\x98\xfd\xf4\xad\x9f\x4e\xbf\xed\xc7\xc5\x4f\xe7\x7e\x12\xa1\x69\xa3\x0b\x37\x71\x85\x58\x18\xce\x26\x16\x90\x59\x06\xb4\xf0\xb0\x42\x34\x14\x09\x86\xec\x58\x93\x0b\xf9\x85\x27\x7b\xad\xca\x55\xeb\x98\xfc\xaa\x1a\x18\x4b\x9c\x28\xc6\xf2\xa3\x00\x8e\x57\x18\x27\x72\x7e\x5e\x91\x1b\x86\xbc\x86\x57\xb1\x7e\xa5\x69\x6c\x78\xe7\xf3\x3b\xe4\x17\xa0\x66\x49\xaa\x1f\x5f\x04\x70\x4e\xe5\xd8\x96\xea\x25\x72\x68\x13\x2d\x8a\x5e\x41\xe6\x74\xd4\x27\x95\x88\x0a\xc5\x82\x77\xad\x13\xd8\x7b\x38\x83\x63\x89\x67\xb5\x65\x15\x63\x9d\x02\x3c\x11\x3e\xaa\x13\x00\x20\xd0\x50\x87\x51\xd8\x9c\xc3\x80\xbe\x9c\x4b\xaf\xd0\x73\x5d\x25\x9f\x89\x88\x07\x27\x90\x3a\xa9\x6d\x1f\x2b\x3d\x34\x6e\x7e\x1e\x72\x9b\x05\xeb\x0a\x5c\x20\x14\x4e\x35\xe5\xdd\x39\x5a\x2c\x00\x5a\xe6\x03\x00\xaf\xbb\x18\x92\x08\xbe\xd1\xe2\xe9\x6f\xf8\x00\xdf\x56\xee\x02\xf1\xa4\xe7\x88\x39\xe3\xdc\x42\x65\x8e\x10\x1e\x28\x2c\x43\x54\x4c\x68\x39\x62\xd0\x15\x56\x8a\x22\x42\xa5\x35\x93\x74\xc2\xee\x58\x85\x8f\x22\xef\xe5\x41\xc4\x4c\x8f\xc9\xa4\xf0\x88\x86\x30\x82\x54\x9c\x2c\x00\x8c\x13\x6d\xe5\x21\xf6\xd3\x9c\xd5\x43\x5c\x2e\x54\x84\xf2\x21\x33\x6a\x42\xd1\x7a\xdd\x4d\x59\x65\x63\x4e\x47\x71\xe9\xcc\x85\x00\x9c\xd2\x39\xde\x7d\x7d\x40\xc5\xc3\x62\x57\x3a\xec\x4d\x38\x60\x7f\x83\x3e\x7d\xcc\x8e\x27\x93\xb8\x33\xef\x63\x37\xcd\xc6\xe4\x07\xbd\x25\xbb\x3e\xea\xf7\x50\x5e\x0f\x10\x08\xaf\xd7\xca\xf1\x59\xc7\x77\xbb\xe1\xc2\x42\xea\x20\x0b\x39\x54\xf5\x2d\xa9\xb4\x3e\x1f\x5a\x79\xee\x2e\x0e\xbb\xc7\xa0\x31\x0a\x50\xc1\x4b\x23\x2d\x7a\x80\x98\xee\x90\xb6\x0a\x77\x7b\x2e\x61\x42\x33\x9d\x7b\xb3\xfd\x22\xc7\xae\xd2\xbb\x70\x82\xb9\x35\x44\x74\xc2\x6e\xaf\x85\x28\xb3\xc3\xaf\x84\xef\x62\x3f\x9b\xbe\x08\x0a\xcc\xab\xf9\x7b\x7b\x5f\x68\x9f\x91\x64\x09\xea\x37\x25\x90\x33\xbc\x82\x43\xd2\x0f\xcb\x1c\x84\x0d\x41\xed\x01\x16\xd6\x04\x15\x6a\xc6\xf8\x0e\x7c\x56\x29\x45\xc7\x94\x02\x16\xd0\x09\x25\xac\x18\xa6\xc8\x19\xe6\xc5\xbb\x4e\xaa\xb6\x4a\x58\x60\x90\x09\x18\xff\xdc\x89\x7f\x99\xdf\xca\x27\xd0\x0d\x98\x0f\x1f\xce\x77\x14\xcc\xa9\xbc\xbc\xfe\x0d\x11\x02\xaa\x50\x28\x2f\x87\xae\x37\x2c\x32\xec\xf2\x86\x0a\x6c\xb3\x9b\x5a\xc2\xd7\x03\xcc\x5d\x68\xab\x50\x05\x34\x26\x42\x1b\x68\x00\xc2\x08\x64\x60\xd5\x51\x87\x62\x4d\x8e\xe0\x8c\x00\xbc\x12\x11\x4b\x81\x86\x00\x7e\x45\x22\x47\x1a\x7e\x0d\x0d\x64\x50\x91\xb0\xad\x71\xd5\x41\x31\x83\x68\x5a\xe7\xc4\xf1\x11\x23\x02\xb4\xd0\xcc\x34\x49\xa9\xdd\x52\xd5\xaf\xec\x61\xfc\x8c\xba\x75\xf9\xda\xca\xb7\x83\x3e\x6c\x58\xf4\xa1\xf5\x99\xf5\x32\x40\x51\x47\x28\x68\x0d\x12\x8c\x9a\x08\xfb\x53\xa8\xcd\x65\x23\x78\x74\xeb\x22\x8e\xcd\x6d\x39\x68\x7b\xce\x41\x13\x00\xfd\x41\x7f\xe9\x01\x23\x3f\x93\x09\xde\xda\xd8\xc7\x2a\xd7\x68\x58\xc3\x35\x9a\x89\xa1\x4d\xc7\x7b\x45\xcd\xbd\x0c\xb5\x7d\x8d\xa8\x56\x8d\xc4\xeb\x26\x99\xcd\x7c\x51\x60\x93\xe5\xbc\x3c\xa9\x60\x16\x3e\x94\xa5\x31\x8a\xa3\x92\x52\x30\x50\x95\x44\xc2\xb5\xec\x76\xda\x10\x29\x8b\x6d\x92\xca\xa8\x98\x21\x1c\x6b\x52\xd5\x19\x52\x18\x88\xba\x98\xc3\x59\x2d\x6c\xb8\x76\x6f\xc5\xab\xf8\x0c\xd1\x85\xe2\x80\x1e\x05\xd9\x3b\x92\x37\x70\x7b\x5b\x31\x33\xac\x08\x53\xba\x42\x69\x6d\xd8\x43\x06\x5d\xd0\x8b\x93\x7e\x31\x4b\x55\x59\x85\x45\xe6\x4a\xce\xa1\xef\xed\xc2\x4b\x20\xd4\xb5\xf2\x8a\xfd\x9a\x68\x73\xc7\xd6\xad\xab\x6d\xa4\xa0\x12\xf7\x7b\xb4\xc5\x02\xb7\xeb\x1b\x55\x2d\x75\xb0\x46\xc5\x54\xd3\x96\xa0\xb9\x4e\xa0\x5e\x1d\xc7\x85\x3b\xae\x20\xec\xe1\x26\xe7\x0e\x55\x86\xb2\xbc\xe7\x36\xfa\x8f\x07\x63\xd2\x44\x55\x7a\x55\xb7\xd1\x52\xad\x29\x86\x11\x82\x0b\x6f\x0a\x13\x8a\x4e\x82\x2d\xf5\x0a\x24\xeb\x2d\x55\xe4\x9b\xc6\xdc\xa1\x38\x9a\x76\xe5\x7a\xd5\x9c\xe9\xc5\x8b\x59\x94\x56\x5e\x8e\xd8\xf2\x0b\xf6\x5a\x8d\x4e\xa6\xab\x4c\xe8\x69\x1b\xd6\xbb\x5f\x80\x12\x3f\x4b\x26\xb6\x7c\x93\xfc\xf7\x97\x60\x68\xc3\x00\x8a\xfc\xec\xd9\xdc\xdb\x20\x5b\x63\xa5\x3e\x62\x68\xbb\xa6\x3c\x39\x62\xfe\x39\x75\x60\x41\x53\x4f\x91\xfb\x75\xeb\x5a\x48\x88\xc5\x75\x94\x78\x2e\xb7\xac\x82\x79\x22\x5c\x03\xe3\xef\x9f\x5d\x05\x17\xc3\x3a\x00\x5b\xec\xa1\xe7\x9a\xcf\xe1\xee\xeb\x32\x9a\xa7\x7e\x1b\xe6\xf8\x67\x08\xa7\xf3\xf3\x48\x84\x82\xe2\x1e\xf8\x87\x50\xff\x76\xe0\xa7\x31\x07\xf7\x50\xd2\xa1\x20\x03\x68\xc5\x91\x13\x95\x9b\x2f\xcb\x52\x7e\x0d\xa9\xa8\xe1\xd0\x57\x50\x59\xf3\x68\x34\x12\xe0\xda\x36\xee\xdc\x40\xc1\x1b\xbd\x05\xc2\xac\xd6\xb5\xfa\x9d\xdd\x21\xd4\x4d\x58\x7d\xb4\xb9\xfd\x1a\xc1\x93\x5d\xa9\x46\x02\x2a\xda\x21\x79\x15\x14\xcb\x5b\xcb\x38\x4a\xc5\x7b\x34\x00\x59\x06\x6f\x79\xb9\x90\x0a\x20\x3a\x52\x6a\x81\x03\xfb\x94\x5d\xc1\x60\xe4\xeb\xb0\x1a\xf4\x53\xb1\x61\x27\x93\xcc\x1e\x95\x1b\xc0\x87\x0e\x73\x55\xd1\xb2\x4d\x61\xcf\x2e\x85\x2f\xd5\x4f\x88\xef\x60\xe4\xee\x00\x35\x9a\xd4\x3b\x45\x52\x3c\xbc\x0f\x30\xce\xd1\x61\x4d\x7d\xe8\x0f\xfc\x61\x2e\x2d\x85\x10\x81\x2e\x3a\xd4\xfd\xac\x1c\x19\x96\x7b\x59\x88\x20\x65\x8f\xe1\x67\x8e\x20\xd4\x94\x00\x8d\xc0\x3c\x31\xc6\x86\x03\x30\xaf\xf4\x00\x1e\xdc\x30\x80\x90\x06\x50\x31\xda\x2e\x6c\x3b\xaf\xfd\x95\xb0\x37\x9d\xb7\x8c\xc6\xdb\xcb\xb7\x53\xb6\xb8\xda\x7a\xb3\xf3\xcc\x53\x11\x01\xb6\xd7\xb7\x5e\xac\xae\xad\x7b\x79\x64\x80\xad\xcd\x2d\x8f\x82\x06\xd8\x27\x50\xb3\xd1\x6e\xd2\x51\xc8\xe1\x71\xeb\x9e\x0a\x75\x70\xef\x45\xdc\xa3\x5e\xaf\xf2\x33\x83\xe7\xba\x5b\xaa\x74\x7b\xa6\x70\x47\xf7\x90\x83\x70\xd5\xf3\xa1\x89\xa4\x45\xfd\x56\x69\xdd\x6f\xa5\x9b\xa1\x95\x9b\x1d\x0c\xc7\xd3\x39\x84\x2b\xe5\x53\x47\x97\x82\xf1\x64\xdd\x72\xbe\xac\x75\x21\xb2\xd6\xa5\x5b\x5b\xc1\x75\x0d\xf4\x99\x3e\x1e\x6f\xf9\x37\x38\x35\xb7\x93\xbd\xde\x30\x70\xf7\xaa\xbe\x3f\xd5\xa5\xb8\x7f\x93\x64\x90\xdb\xfb\x73\xe5\x67\x86\x7f\x15\xf9\x99\x71\x75\x4e\xeb\xe2\x85\x2f\x2c\x28\xff\x2b\x41\xfd\x04\xef\xa0\x3b\x93\x39\x58\xd4\x24\x00\x7a\x0b\xa6\x8d\x18\x70\xca\xf0\xed\x30\x20\x61\x1a\xd9\xbd\x99\xbe\x0a\xa2\xd1\x1b\x4d\xdd\x82\xdb\xb1\xf4\xc7\x4a\xde\x54\x8a\x11\xd5\xc5\x95\x85\xfa\x79\x57\x4c\xa6\x42\xe7\xcd\x5c\xa3\xd2\xfd\x0c\x0b\x75\x32\x24\xc7\x2b\xaa\x75\x70\x40\x95\x1e\x1c\x48\x44\x64\x7d\x4b\x6c\x61\xab\x6b\x64\xd6\x6e\x08\x48\xf3\x8a\x2d\x01\x58\xc4\xa6\x22\xc3\xd7\xbb\xa4\x31\xbc\x4d\x44\x7e\x45\x08\x3f\x8a\x7d\xc7\xca\xd9\x35\xbc\x43\x1b\xa7\x28\x2a\x69\x13\x0d\x1c\x5c\x3b\x7e\x6b\x4d\x63\xea\x65\x25\x0a\x5b\x55\xf3\xfe\xed\x04\x39\x7f\x51\x27\xea\xaf\xfa\xe6\xd2\x1e\xe0\x6c\xbc\xde\xb7\x04\x62\xac\xcb\x9d\xe4\x9e\x03\x34\xc3\x7a\xfc\x4b\x6e\xc4\x90\x37\x22\xec\xa2\xd4\xed\x8c\x5b\xc6\x9d\x80\xe4\xc0\x2b\xb1\x12\x4e\x0a\xe2\xe5\xc4\x2d\x12\xcc\x09\xbd\x01\xcd\x0b\xc5\x19\xc4\x67\xe8\x4e\x81\xfa\x18\x6b\x7e\x1e\x19\xa1\xca\x2b\x9d\xd5\xb7\x71\x80\xb1\xba\x82\x0a\x18\xb0\xc8\x65\x6e\xf7\xbf\x14\xe5\x69\xf1\xee\x7f\x85\x7b\xfa\x73\x04\x6c\x25\x87\x7e\x87\xe3\x2c\x8b\xa3\x29\xce\x22\x61\xb9\x4e\x82\xcc\x7f\x1e\x5c\x12\x7a\x34\xcc\x54\xaa\x97\x25\x43\x95\x24\xdd\x40\x48\x33\xf6\x5c\x03\x36\x7f\xc9\x83\xe3\xff\x55\xbc\x8a\xd2\x3f\x42\x0b\x0d\x2d\xc6\xf6\x55\xd4\x9b\x2d\x72\x1c\xd6\x40\x96\xd1\x74\xa0\x11\x7f\x36\xd0\x48\x19\x68\xf8\xf9\xed\xc5\xa7\x7a\x6d\x18\x62\xc4\xbf\xaa\xbf\x17\xe2\xf1\x88\x08\x36\x4e\xa7\x60\x5f\x45\x05\x48\xfa\x54\x7d\x4d\xe1\xec\xe6\xd9\xbf\x6a\x42\x7f\x1d\x07\xf9\xa5\xf3\x6d\x3c\x7c\x06\xa8\x04\x67\xe4\x0e\x06\x3f\x2c\xb9\x14\x10\x0f\x43\xaf\x92\xc9\x37\x7e\x51\x5c\x73\xd8\x4c\x91\xb2\x55\x9e\xa9\x33\x67\x19\xe0\xc5\xb6\x29\x18\xf3\xa1\xed\x37\xc4\x8d\xb6\x78\xe5\x47\x41\x86\xca\x7b\x37\x5c\xe0\x53\x55\xfe\x3e\xb7\x61\xbb\xdd\x35\x6d\x4b\x34\x55\xf2\x58\x67\x78\x54\x90\x42\x42\x2d\xcc\x9e\x60\xe3\x38\x97\x25\x92\x0d\x3c\x02\x79\x51\x9f\x72\x98\xd6\x90\xff\x6e\xf5\xc2\x2a\xff\x79\x93\x90\x73\x46\x7e\xf6\x24\x4c\x45\x9e\x78\xf8\x3d\x14\x48\xe4\xa5\xc5\xd5\x31\xaa\x66\xea\x81\xd3\x02\xb8\xa2\x64\xbb\x65\xcf\x2b\xd9\x5b\xd1\xa6\xf4\x2c\x51\x35\xbd\xb0\x99\x28\x46\x47\x27\x53\x53\x45\x96\x4b\x6a\xdb\xd5\xcd\x70\x8b\x0c\x9e\x64\x21\x3b\xdc\xef\xad\xc7\x9b\x2f\x5b\xe8\x59\xa2\x06\xe7\x73\x35\xd2\x37\xb6\x91\xbe\x51\xcb\x66\x07\x4a\xcd\x0e\x1c\xd6\xb1\x03\x47\xf6\x25\x5f\x5a\x52\x28\xc1\xf7\xbd\xed\x4f\x27\x8b\xe1\xb5\xe5\xd5\x47\xe7\x11\xaa\xfa\xa2\xaf\x1e\x5e\x2b\x2c\x41\x50\x49\xd0\x4a\xe5\x8f\xd6\x48\xf3\x97\x7a\x72\x87\xac\x7b\x03\x5d\x2c\xe2\x0c\xe5\x5e\x36\xf8\x45\x43\xd8\x56\x74\x36\x3e\x31\xaa\xc5\x27\x6e\xad\xb6\x73\xff\x56\xda\x34\x7f\xc4\x94\xff\x88\x29\xff\x53\x84\x29\xdf\x24\xb6\xfc\xe3\x9e\xfe\xcb\xb4\xa7\x7f\x69\x86\x43\xbe\x7b\x7d\xb7\x93\xda\xbb\x57\xed\x57\xb5\x7b\x91\x2b\x9e\x3f\x01\xe8\x37\x69\x6b\xe7\xe2\x4e\xbe\x16\x69\x69\xbf\xda\xdb\x34\xbd\x71\x9b\xe2\x96\xbc\x9d\xf4\xeb\x8f\x2c\xbe\x3f\xb2\xf8\xfe\xa2\x58\x7c\xb3\x75\x35\x4b\xe7\xb5\x57\x7b\x07\x0d\xff\x40\x7c\xc2\xd4\x81\x19\x40\x25\x28\xe5\x16\x29\x25\x1f\x48\xa8\x49\xcf\x48\xe0\x9c\x99\x11\xea\x4f\x1c\x0d\x2f\xe7\xa0\xd3\xb6\xd6\x1e\xac\x19\x57\x1f\xf4\x1b\xa2\x22\x52\x27\x15\x95\x5a\x9e\xe3\xb0\x72\x1b\x8e\x0b\xb7\xe1\xb8\x0c\x43\xc6\xec\x58\xb1\x4e\xf1\x04\xbe\xa1\xa7\xc4\x6b\xc0\x2e\xeb\xaf\xc3\x9e\x0d\x67\x86\x33\xe1\x8c\x75\x03\xd6\x23\x7f\x15\x81\xfc\xfd\x9b\x44\xae\x7f\x04\x49\x7f\x04\x49\x7f\xe1\x20\xa9\x75\x6f\x8d\xc9\x3b\xed\xa6\xa3\xa2\x3b\x5e\x66\x01\xf5\x6a\xc0\xd5\x10\x43\x25\x27\xd6\xb9\xc0\x20\xc9\x33\xf8\x42\xbf\x04\xb4\x42\x2a\x1a\x51\x60\xd5\xff\xa9\x8c\x01\xa6\x58\x1f\x07\x23\x80\x16\x55\x1e\x01\xbd\xc7\x20\x11\x46\x31\xb1\xac\xcc\x54\x53\xb1\xad\x9c\x44\xd0\xc0\x00\xac\xdc\xd1\xd4\xee\x70\xdf\xad\xad\x94\xd5\x9d\x7e\xd1\x5a\x51\xe5\xeb\x4d\x74\xf2\xf9\xbd\x25\x47\x24\xa6\xbe\xda\x3c\x75\x3c\xb7\x3a\x56\x4b\xaa\x94\x5f\x4c\xc1\xd5\x8c\xe6\xd6\x78\x06\xdc\x36\xd3\x4d\xa1\xe2\x6d\xfe\x4e\xfe\xe9\x73\xd8\x3b\x54\xa0\xa4\x50\xba\x66\x94\xe8\x35\x80\x9e\xc6\x32\x94\x75\x83\xd0\x7d\x99\xd5\x77\x76\x55\xc1\xba\xeb\x15\xf3\xbd\x48\x8e\x89\x21\xc4\x21\xf9\x34\x4f\x08\x59\x42\x43\xcd\xbe\xb8\x9d\x3e\x92\x62\x6e\xdc\x4e\xf3\xc8\x70\x87\xfc\x92\x13\x1b\xa3\x58\x4d\x6a\x41\xb7\xe3\x68\x71\x93\xf5\xb3\xe9\xe4\x7c\xa8\x6e\xb9\xad\x94\xcd\xc0\x33\xd7\x2b\x7f\x41\xff\x43\xe1\x28\x53\x0e\x7e\x6b\xaf\xf9\x5a\x2e\x13\x9f\xd9\x5e\x8d\x1f\x66\xc5\x84\xea\xd5\x33\xa1\x7a\x16\x58\xb8\x55\x7d\x37\xf3\x77\xaa\x70\xd2\xbb\xbf\xf4\x19\x5c\x9f\x1a\xf5\x92\x82\xe7\xf0\x99\xba\x57\xe6\x62\x46\xeb\xe4\x00\xdd\x4f\x94\x7d\x9e\x40\x15\x00\x41\xe1\x76\x66\x67\x26\x75\x9e\x4c\x6c\x59\x14\xe9\xf4\x90\x1f\x1c\x4b\x55\xb7\xa2\xc4\x8b\xda\xc4\xf3\x05\x4f\x2e\xba\x23\x29\xdc\x11\x81\x6d\xd8\xca\x8e\x32\xc6\x35\x8e\x32\x52\x39\x46\x47\x19\xe1\x6e\x8a\x7d\x8b\xe0\xa7\xdc\x37\x18\x25\x76\x04\x39\xf1\xbe\x88\xd1\x2d\xa5\xe9\x6a\x5c\x1a\xbf\x48\xa0\x9d\x30\x77\x03\x10\xae\x24\xd0\x4e\xe2\x46\x32\xdb\x4d\xf6\x45\xa4\x2d\x5e\xcc\xf9\xdc\xe5\x57\xfb\x6c\x4d\x31\x43\x85\x9f\xf6\x07\x19\xc9\xf4\xb5\x61\x28\x23\xa5\xc2\xd4\x21\x01\xb5\x88\x6c\x2b\x1d\x8c\xd6\x57\x78\x01\x7d\x2d\x04\x69\x2b\x98\x22\x4f\xd7\x91\xd6\xca\xda\xd7\xc5\xc8\x8c\xf5\x2b\xcf\x76\x40\x0e\xae\x35\x3a\x69\x55\x8f\xb4\xe6\xb3\x16\x7d\xfc\x0b\xd7\xd7\xa3\x6b\x00\xf5\xec\x00\xda\x5d\xb0\x08\x25\x53\xc7\x0c\x40\xdc\xb5\x76\xdc\xb7\xbb\x2f\xd0\xd1\xee\x50\xe9\xfd\x4c\x26\x8f\x11\x7f\x50\x2a\x3a\x1a\x2f\x9f\x4c\x3e\x89\x33\x24\xf2\x5f\xe1\x9f\x55\x56\x27\x7c\x41\x3f\x9d\x8a\x45\x11\x21\x91\x64\x7f\x72\xe0\x24\x2e\x60\x7b\x36\x72\x7c\xd0\x1d\x39\xf3\xc7\x93\x49\x03\xed\x56\xd0\x5e\x38\x02\xfc\xf4\xac\xf5\x6a\xf3\xf1\xfa\xc1\xfa\xab\xb7\xb5\xb6\x44\xfe\x1c\xab\x86\xcf\xe9\x4e\xe2\xdc\x90\x6e\xf3\x5c\x90\xeb\xdb\x02\x86\xd7\xf3\x31\x3b\xda\xdb\x28\xaa\xe7\x1c\xae\x5d\x4d\xdc\x7c\x02\xd8\x82\x05\xd3\xcb\xa8\xc7\x26\x49\x98\x51\xf9\xb0\x44\x83\x9c\x86\xeb\x0d\x1c\xe8\x1a\x10\x3b\x41\xd0\x4f\xa1\x7a\x12\x38\x71\x97\x7a\xb9\xb6\x35\x50\x59\x45\x05\x6b\x44\x64\x13\x58\x9a\xa3\xc9\x64\x03\x95\xb3\x61\xf4\x97\x3c\xbd\x1f\xe5\x70\x86\x23\x7f\xda\x93\xe4\xf9\x4c\x29\xbe\x03\xbc\x1b\x47\x91\x76\x98\x4d\x3a\x71\x5b\x70\x15\xc0\x8b\xd7\x46\x50\x65\x5f\x07\xab\x30\xd3\xab\x4a\xe5\x11\x2e\x24\x5e\x17\xd4\xdd\x46\x3f\x96\xab\xc3\x61\x55\xd7\xf5\x63\x6b\x4a\xb5\x50\xfc\x23\xed\x73\x6d\xf5\x06\xeb\xfc\x51\xbb\x12\xd9\xdd\x07\xc4\xb4\xdf\x2f\x57\x07\x1b\xcc\x6c\xac\x75\x92\xd8\x21\x38\x28\x54\xe3\x9a\x4a\xc8\x62\x4e\x61\x90\xfa\x1d\x85\xcc\x53\xba\x79\x35\x95\x43\x67\x0b\x03\xa1\x3e\x9a\x7e\xa0\x25\xff\x47\x44\xb9\x00\xdb\x27\x55\x65\x32\xf3\xae\x53\xe1\xdf\x6c\x19\x97\x27\xc5\xa6\xa7\x7a\xfb\x20\x62\x0a\xb1\x88\x2d\xdb\x38\x0c\x46\x08\x47\x85\xfd\x7d\x2b\x9d\x59\x7b\x6b\xbf\xee\x66\x5e\x61\xf0\xbb\xd9\x7e\x67\xe0\x84\x85\x3c\xe2\xae\x22\x03\xb1\x4b\xb0\x7f\xaa\x60\x8d\x5c\x6f\xb1\xe9\x97\x46\xad\xb7\x5a\xc6\xde\x1c\x7b\x64\xf9\x12\x70\x48\x0d\x73\xa6\xd3\x11\xee\xe9\xc7\xb2\x9b\x12\x03\xdb\x61\x93\x9f\x74\x1b\xbf\x6a\x34\x43\x2f\xbc\xc1\xed\xc8\xb4\xaa\x56\xbb\xc6\x73\x88\x13\xba\x5e\xc2\xd6\x91\xe1\x0d\xfe\x47\xf2\x32\x95\x1a\x67\x79\x1d\xd9\x51\x77\xcb\x4a\x1b\x8e\x2a\x74\xfe\xb2\x8b\x41\x4a\xc8\xab\x32\xd0\xab\x9e\x33\x22\x56\x88\xf6\x43\x32\x77\xee\x1b\x13\x42\x1b\x42\xc0\xd5\x12\xa6\x00\x1a\x34\xa4\x50\xfe\xaf\x80\x52\x9a\x6f\x1b\x3f\xa9\xab\xa8\x18\xeb\x65\xad\x38\xa2\x54\x31\xd2\x2a\x6a\xf8\x16\x20\x5b\xd5\xa1\xf5\x9b\x88\xeb\x81\x85\xc6\xf2\xf0\x9b\x4f\xef\xfc\x1c\x6b\xdc\x7a\x48\x7e\x02\xdd\x69\x57\xf5\x12\x4d\x4c\xec\x17\xdb\xdd\xfa\xc9\x22\x51\xa9\x91\x90\x6a\xb1\xb4\xa7\xe6\xc3\x8c\x83\xba\x43\xe3\xa0\x54\x71\x1c\xdc\xeb\x4c\xe7\xd5\x0a\xa0\x6b\xf0\x78\x14\x94\xce\x23\x82\x2f\x3a\x46\xca\xa5\x14\x74\x00\x60\x3e\xb4\xa3\x3f\x14\xac\xba\x66\x82\x1b\xc5\x4c\x39\xe3\x8a\x62\x15\x56\x2d\xc2\x43\x87\xb0\x14\x26\x3b\x86\x25\x07\x92\x1f\x96\xb8\x4f\xda\xb1\x0b\x0b\x78\xdc\xab\xa6\x41\x70\xc9\xa8\xd0\x6c\x1f\x95\xab\x07\x44\x57\x73\x17\x13\xaf\xd4\x22\xcf\xb1\xcf\x8f\x34\xb7\xd3\x6c\xcd\xbd\x84\xa9\x9c\x4b\xc7\xb0\x1b\x2e\x01\xc8\x13\xda\xc1\x76\xba\xca\xe4\x16\x32\xad\xcc\x21\x62\x70\xce\x5b\x26\xc2\x7c\x8a\xa9\x96\xc2\x59\xc5\xd3\xca\x3d\xf7\xd1\x02\x13\xad\x80\x3a\x0a\xff\x82\x6b\xf4\x4c\x01\x9b\xc9\x04\x6e\xd9\x21\x8d\x95\x2d\xda\xc8\x8f\xca\x99\x36\x6a\x83\x27\x74\xda\x65\xe5\x3d\x91\xbe\x9d\xf7\x08\x1e\x4d\xde\x4e\x4f\x07\xf0\x73\xd0\x7c\x7b\xaa\x3d\xd8\x7c\xe8\xc0\x02\x89\xa1\x38\x11\x03\x71\x84\x0e\x34\xc7\xf2\x78\x66\xf6\x5e\x21\x3b\x1c\x25\x84\xfc\x58\x8a\xc7\x74\x49\x77\xfa\x39\x81\x78\xeb\x5c\xb3\x10\xfc\x23\x9a\xf3\x74\x56\xe5\x25\x65\x3d\x00\xe4\x93\x9d\x8f\xe8\xce\x2e\x6a\xb3\x59\xb7\x73\x4e\xda\xf7\xce\xa5\x48\xc5\x41\xee\xda\x04\x70\x9f\x3f\xd1\xfe\x39\x26\x93\x4b\x5b\x29\xbd\xfb\x82\x6d\x2c\x3f\x02\x6c\xb8\x54\x9e\x1c\xce\x61\xeb\x43\x15\x63\xe8\xee\x51\xa1\x12\x3b\xaf\xb2\x42\x64\xc1\x33\x1c\xb5\x48\x68\x6b\x3b\xcf\x37\x86\x77\x42\xa1\x44\xc7\x9a\xfc\x3b\x51\x94\xdd\xd1\xb5\x4b\xff\x00\x8a\x8d\x8b\xa6\x61\x03\x67\xfe\x63\xcb\x5c\xd6\x42\x5d\xe4\x08\x50\xfc\x21\xdc\xf6\xfd\xcb\xb9\x84\x3f\x01\x38\x79\x91\xf3\x58\xb4\x91\x01\x6e\x64\xeb\x60\xa2\x13\xad\x55\xc4\x84\xf0\x36\x67\xd4\x2a\x2a\x0c\x5f\xe7\x5e\x65\x23\x86\x82\xbe\x3e\xc6\x29\xe0\xf1\x7e\x04\xe4\x2c\x21\x73\x88\x02\x54\x42\x74\x04\x2f\x4d\x3e\xcf\x2f\x00\xcc\x05\x51\x00\xe7\xaa\xe6\xa5\xa3\x1b\x2a\xc2\x00\xbc\x66\xcd\x60\x89\x27\x58\xb8\x76\x55\xb2\x88\x65\x18\x40\x51\xb5\x29\x52\x34\x26\x60\x3d\x45\x8f\xf6\xb3\x50\x13\x84\x7e\x27\xf1\x59\x50\x1d\x44\xdd\xfb\xdb\x8d\xa3\x4d\xe6\x40\x3a\x4b\xcd\x45\x93\x58\x16\x82\x86\x41\x5d\xcd\xd6\xcb\xcd\x8a\x14\x53\xa2\x86\x95\xa1\x21\x81\xe5\x82\x26\x40\x97\x50\x62\x1a\x53\xa6\x04\x48\x31\xb3\x8c\xa8\x25\x6b\x32\x6b\x7a\xc3\xf0\xb4\x9c\x71\x8a\xf9\xd6\x99\x39\x04\xc5\x02\x53\xec\xb4\x34\xfc\xb2\x33\x4f\x33\xc8\x52\xc0\xcd\xce\x3a\xd5\xf2\x4a\x4f\xce\xcd\xb6\x55\x25\x74\xac\x8b\xee\x50\x79\x10\x9e\xef\x9c\xe5\xa8\x1d\x9a\xf0\xeb\xde\x8a\x80\x34\xc3\xf8\x7a\x99\x4c\xc6\x8e\xea\x1a\xa1\x19\x80\x37\x85\x17\x70\x5c\xbc\xdd\xc3\x7d\x3b\x9c\x96\x11\xdd\xaf\x69\x81\x67\x85\x65\xe1\xd9\x2c\x8b\xb5\xe9\x2c\x90\xb5\x29\x66\x79\x36\x6b\x74\x36\x4f\xb4\xad\xab\xfa\x38\x3b\x3a\x92\x9e\x4e\xf9\xea\x56\x91\x60\xca\x91\x2f\xa0\x5c\x39\x20\x88\x62\x59\x16\x8f\x29\x1e\x5c\x3e\xf8\xf5\x1e\xc5\x3f\x56\x98\x74\x4b\x16\x53\x6a\x58\x62\x3d\x65\x86\x01\x96\xf3\xe3\x94\x3b\xca\x9c\x6b\x56\x43\x09\x68\xfb\x68\x04\xa6\x16\x4d\xa0\xde\xc2\x59\xbf\x66\x3f\x08\x16\x3b\x7d\x34\xcd\xe5\xca\x60\xba\xe8\xef\xf8\x33\x0d\x9d\xfb\xcc\xb2\x9f\x6e\x1e\x74\xc6\x19\xb4\xad\x6e\x7a\x6f\xe3\x24\xc4\xe9\x7f\x04\x58\x58\x1a\x24\x1a\xd0\x40\xce\x13\xce\xa9\x89\xde\xf4\xde\x33\x3f\x3d\xd6\x15\xc2\xf7\xa3\xca\x77\xc6\x61\xad\x2c\x97\xe5\x2c\xdb\x0c\xac\xad\x2c\x07\xe5\x2c\x3b\x44\x8d\x5a\x39\x0e\x39\xc7\x8e\x6d\xd7\x0c\xaf\xd7\x55\x48\xbb\xdc\xf6\x3f\xc5\xd8\x00\x14\x59\x4f\xc7\xaf\x81\x6c\x17\x2a\x04\x6f\x5a\xfe\x70\xce\x1f\x72\x38\x0f\xef\xd6\xaa\xd6\xae\xdb\x65\x13\x44\xb1\xc3\x6f\xf2\x9e\xbc\xac\xb5\x5d\xdc\xe4\xb7\xec\xe9\xd2\x15\xaf\x8b\xfa\x15\x1b\xfc\x98\x8e\x47\xc4\x54\xcc\x2b\xdb\xaa\xba\xdf\x79\x2c\x8f\xbb\x27\xe8\x83\x43\x7c\x82\xd4\x19\x6d\x4e\xcb\xd4\xa2\x57\xf0\x04\x0e\xa5\x51\xa0\xd3\x0b\x52\x28\xea\x4e\x37\x6f\xd3\x2d\x7a\xed\xdf\x08\xd3\x4d\xaf\xfd\xb5\xa8\x3a\x31\xa8\x93\x70\x5a\xc6\x71\x96\x66\xc5\xf2\x7d\x51\x59\x29\x6f\x99\x22\x2f\x5b\xf3\xec\x2d\x53\x0f\x66\x98\x7c\x89\xdb\xec\x50\x6f\x99\x3a\x3b\x7b\x03\x78\xf7\x29\x53\x79\xf9\xbd\x07\x34\x8c\x29\x7b\xdb\x7b\xb0\x2c\x66\xee\x6c\xef\xc1\x7d\x31\x73\x5f\x7b\x0f\x1e\x88\x59\xbb\xda\x7b\x40\xaa\x52\xe5\xe5\xf7\x1e\x7c\x2d\xf4\xea\x79\x0f\xea\xb9\xc7\x9f\x6f\xeb\x3d\xc3\x9f\xc4\xfd\xcf\xf7\x8b\x4c\x3c\x3d\x20\x2d\x3f\x45\xf1\x79\x94\x0b\x81\x0c\xeb\x37\x99\xce\x83\x4e\x5c\x4d\xc3\x07\xbb\xc9\xbe\x83\x46\x9c\x40\x2a\x15\x18\x14\x84\x91\x2e\x2c\xf4\x90\x88\x0e\x5b\x27\x30\x0f\xfe\x11\x0a\xfe\x8b\x86\x12\x8c\xd4\xb0\x20\x05\x23\xf5\x18\x29\x86\x06\xd8\xe4\xef\xce\xf8\x7c\x8a\x5a\xc8\x88\x7b\x6d\xb1\x16\x72\xd7\x32\x95\x8f\xb8\x87\x50\xfc\x60\xf3\x98\x89\xda\x46\xbf\x52\x6f\xd1\x7b\x93\xb9\x3a\x72\x07\x02\x2d\x16\x2d\x73\x97\x82\x82\xf2\x00\xa9\x83\xe3\xa5\x62\x70\xaf\x5c\x61\x01\x59\xda\x26\xce\x03\x32\xe5\x84\xf5\x51\x50\x80\x40\x29\x87\xdd\xe3\x56\xd5\x89\x8b\x13\x3a\x80\x40\x78\x98\x61\x64\x32\x14\x5c\xb1\x58\x39\x06\x26\x87\x3e\xb8\xea\xe3\x71\xc1\x77\x0a\xbe\xb3\xc3\x8a\x45\x46\xf3\x77\x61\xc1\x77\x22\x4b\x0f\xd8\x5e\x11\x3f\x5f\x91\xdd\x7d\x3d\xc8\x34\x8f\x21\xa6\x5d\x54\x66\xc2\xc6\x4b\x9d\x4c\x52\x28\x3b\x92\x6a\x23\xbb\x06\x1d\x86\xc0\xb4\xb3\x8b\x4b\xeb\xd6\xbc\x8d\xb0\xb9\xee\x52\x1d\xe6\x21\x4f\x69\x87\xa6\xf7\x0a\x3e\x70\xd4\x75\x5c\xc8\x50\xf4\x64\xa3\xee\xe5\x42\x0e\xeb\x1a\x38\x2e\x00\xf4\x59\x1e\xfb\x66\xf4\xc2\xbb\xdf\x16\xb3\xfa\xe0\xdd\x2f\x17\xcf\x21\xef\xfd\x29\x00\x62\xa6\xa7\x99\xf2\xf9\xbf\xc9\xb0\xd6\x3a\xff\x06\xc1\x0b\x9d\xdc\xfd\x07\xa0\x5a\x86\x87\xad\xdc\x80\x8c\x14\x5f\xa4\xe2\xf6\xfd\xea\x42\x1b\x04\x8f\xe0\x50\xbf\xe7\xe0\x39\x93\x49\x3f\xee\x91\x28\xbf\xa5\x13\xea\x7c\x29\x19\xc0\x8b\x60\x90\x89\x4b\xbb\xe4\x87\x5b\x96\xc4\x90\x50\xbf\xb0\x23\x99\x92\xa9\xf0\xef\xeb\x82\xe3\xc1\x4d\x76\xc6\x51\xcb\xde\x2e\x37\xed\xe8\xa8\xf5\x22\x8c\x3e\x55\x72\xe1\x4b\xfa\x5a\xd8\x5b\x37\xee\x7e\x8c\x52\xac\x7c\x21\xcc\x38\x06\x90\xab\xb6\xb6\xbc\x16\x26\xa9\x94\x7c\xb8\x3e\x5f\xae\xc0\xa6\xaa\xd3\xb9\x4b\xa5\xe1\xb3\x7d\x51\xdf\x80\xa0\x42\xe6\xe2\xbd\x7d\x33\xc2\x8a\x63\x2e\xdc\xe4\x37\x23\xb0\x51\xab\x78\xb7\xdf\x88\xcf\x46\xad\xd7\x41\x9a\x4d\xcb\x6e\x7f\xa3\xcc\xf5\xd8\xcf\xad\xb1\x78\xe8\x9e\x3a\x0c\x70\x1c\xa6\x95\xae\xc9\x62\xcf\x5f\x19\xe1\x85\x9d\x04\x79\x8e\xac\xfe\xe7\xcf\x66\x46\xd4\x96\x60\x9b\x1c\x12\x8c\xe6\x37\x4d\x01\x74\xda\x1f\x4c\xb6\xea\xb6\x2f\xe6\xb6\xbf\x9b\x42\x35\xfb\xbb\x58\xaa\x90\x21\xef\x52\x61\x9b\x97\x7a\xa5\xbe\x15\xfb\x5f\x45\x34\x6f\x47\x8c\xe8\x4a\x2a\xb9\x79\xba\x93\xb1\xaa\x07\x12\xfa\x35\x5f\x26\x25\x6c\xdd\x9a\x6e\xaf\xfd\x4d\x15\x01\xa7\x39\xf7\x96\xbf\xfc\x1c\x3c\x7a\xf6\x6e\xf0\x96\xbf\xf9\xbc\x7b\x8c\x80\x8e\x77\x7f\xf9\xf7\xb9\xde\xea\x20\x8a\x32\x32\x98\x06\x41\x50\xdb\xb2\x3c\xb5\xde\xfd\xdf\xdc\x9a\x50\xf8\x43\x53\x04\x53\x00\x81\xf7\x80\x86\x95\xef\x0b\xef\x01\xfa\xc5\x78\x70\x93\x55\x7d\xad\x05\xb2\xf2\x92\x33\x99\xc4\x55\x8c\xb6\xd6\x22\x99\x4a\x4f\x26\x45\xbf\xda\x14\x7f\xb5\x15\x9c\xa1\x50\x30\xd1\x66\xc8\x39\xde\x56\xf2\xf1\x61\xfb\x02\x78\xf0\x79\x76\xd3\xc8\x64\x4b\x95\x04\xc6\xd1\x1a\x24\x4d\xd9\xd6\x1a\x04\xcc\x64\x1f\x55\x19\xbd\x88\x93\x7b\x19\x0a\x2c\xaa\x5e\xd2\xd1\xdf\x1f\x11\xcd\x23\xd4\xc9\x28\x0c\x5b\xf3\x91\xaa\x35\x6a\x67\xe3\x65\x17\xf3\xdd\xf9\x25\xcf\x19\x19\x09\x19\x7a\xcb\xcc\x58\x90\x67\x11\x11\x2a\x9a\xad\xab\xab\xf7\x3b\x3e\x33\xdb\x61\x90\x93\x49\x8a\xae\x54\x5c\x46\x57\x7c\xa5\x78\x39\x8b\x8d\xa3\x55\xc2\x73\xa0\xdc\x93\x24\xe4\x01\xba\x69\x24\xaf\x2a\xbc\xf5\x02\x4f\xb8\xa7\x31\x6e\x01\xfd\x11\xc3\xc9\xc4\x51\xd8\x15\x14\xa3\xa8\x78\xba\x54\x77\xca\x7b\xa7\x01\x94\xdd\x71\x8f\x5a\x68\x88\x18\x87\xaa\x11\x34\x3f\xcb\x60\xa6\x29\xb7\xd3\x88\xa3\x42\x3e\x44\xca\xe7\x97\x88\x75\x57\xe5\x9a\x17\x7b\x58\x23\x59\xca\x75\x65\x02\x14\xd0\x01\xb5\x80\xa6\xf4\x3d\x13\x7b\x58\x0f\x82\x2b\xaf\x1d\x47\xcd\xa7\x19\x43\xb1\x72\xd7\x0f\x05\x25\xb5\x38\x93\x85\xae\xfb\x6a\xb3\xea\xc8\x46\xfa\x44\x23\x31\x0c\x34\x83\x91\x49\x57\x0a\x29\xaf\x3b\x95\x72\x7a\x5b\x95\xdf\x6b\xde\x79\xb3\xfc\x21\xa5\x70\x5f\x4d\x94\xa9\xa3\x96\xc1\xa8\x28\xe7\xa0\xfe\x6d\x6e\x89\xb1\x8e\xb5\x74\x33\x53\xbf\x1f\xf4\xe2\x7e\xf0\x66\x7b\xa3\xd2\x07\xb4\x65\x6d\x01\xf5\x1a\xc2\x0c\xfd\xaa\xe1\xee\xb6\xf7\x27\x13\x72\x50\xaf\xfd\x11\x57\x6b\x6b\x3c\xb4\x21\xeb\x4a\xa3\xe0\x7f\x47\xeb\xd6\x15\xef\xbb\x9b\xdc\x03\x3d\xb8\xc9\x64\xb2\x08\x50\x6c\xb0\xd1\x9b\x0e\x36\xd2\x59\x60\xa3\x57\x01\x1b\x58\x71\x1e\x7d\x9c\x5c\xfb\x21\x79\x1f\xf3\xc1\x36\xe0\x71\xe6\xa9\xf6\x2b\xa7\x5a\x89\x40\x51\x1f\xe7\xa6\x53\x9d\x9a\x53\x3d\xfe\x39\x27\x1a\xb6\x49\xca\xf6\xd3\xe1\x8c\xf3\x6c\xe5\x42\x20\x74\xbb\xd3\x9c\xc2\x96\xbb\xdd\x69\x4e\x2b\xa7\x79\xda\x00\x6a\x8f\xf2\x94\x31\x94\x0e\x72\x79\x0c\xb5\xc7\xb8\x14\x97\x0c\xbf\xab\xd8\xad\x2c\xd3\xbd\x16\x8d\x06\xf9\x21\xc8\x2f\x24\x41\xab\x0d\x47\xdf\xad\x3f\xe4\xa5\x2a\x55\x96\xda\x5a\xb1\x26\x05\x0f\xd4\x09\xf6\xe9\xb8\xfe\x3e\x67\xf5\x06\x78\x71\xd3\xa1\x2d\x22\x3c\xa5\x73\xdb\xfb\x79\xe7\xf6\x76\x66\xa1\x36\xf5\x61\x91\x46\x61\xe5\xb0\xc4\x70\xa8\xa7\xac\xe3\xd0\x90\x5b\x33\xd7\xa6\x02\x74\x35\x00\x0d\x6b\xa7\xbf\x2c\x5d\x9e\x39\x83\x25\x8c\xb0\x34\x83\x71\xed\x0c\xd6\xe1\x99\x38\x71\x9f\x11\xba\x11\x20\xbe\x53\xd2\x22\x3c\x89\xfb\xe1\xe0\xb2\xaa\xd7\xd8\x70\xff\x18\x82\xed\x2f\x26\x50\x83\xcd\x82\x9a\x1a\x8a\xad\x36\x08\x9b\x0c\x6a\x42\x14\x14\x77\xe1\x4d\x7e\xbc\x7c\xcb\x28\x62\x46\xdc\x00\x2e\x73\xf7\x61\x91\x50\x99\x1e\x0b\x40\xb9\xc4\x4e\x2d\x6f\x98\x78\x1a\x65\x22\xec\x57\xea\x60\x95\xde\xc2\x11\x2b\x04\xcb\x4c\x8b\xcc\xb5\x2a\xe3\xec\x8f\xa6\x72\x7f\x28\x53\xb9\xa9\xfb\xd8\xbf\x11\xbd\x49\x2b\x10\x7b\x3c\x7d\xef\x27\xc5\xbd\xaf\x6e\x4d\x0c\x23\x01\x18\x11\xbd\x1a\xaa\x7b\x9f\x70\x24\xdb\x86\x49\x03\x4d\x9a\x73\xc7\x32\x43\x37\x07\x46\x6b\x58\x37\x10\xa2\x57\x37\xfd\x7c\xbb\x6c\xf2\x54\xa8\xb2\xce\x00\x56\xad\xb0\xb4\x3b\xab\xde\xe5\x75\xc1\xa6\x02\xc0\xbb\xa6\x88\x88\xaa\xdd\x91\xde\x35\x1a\x3b\x35\xce\x60\xea\x10\x54\x01\x7b\x0b\x75\xe7\x0b\x53\xa1\x37\x5a\xb2\x12\x75\x9a\xcd\xc8\x2d\x7e\x85\x2d\x67\x89\x8a\xad\xf0\x21\x15\xcc\x72\xaa\x51\x57\xde\x92\x96\xda\xe4\x56\x43\x55\x34\xf0\xe6\x6a\xca\xfd\xbf\x11\x4f\x34\xed\xb1\x8f\xd5\x29\xf5\xdb\x78\x9b\xa3\xf7\x50\xfd\xf6\x50\xdf\xec\xb5\x71\x7c\x85\xc7\xe5\x63\x53\x0e\x5c\xab\xcd\x29\xc7\x4d\xc5\x25\x2f\x5c\xb7\xaa\x70\x41\xdf\x9f\x74\x40\xc9\x0a\x20\x8a\x2d\xe5\x5f\xbb\xaa\xdd\x9a\x7a\x17\xdb\xfb\xda\xbd\x72\xb9\xc3\x06\x5d\x34\xf3\x13\x8f\xa6\xd9\xfa\x99\xd9\x21\xb5\xe5\xcf\x9f\x1b\x62\x55\x88\x9f\x71\xf7\xcc\x1e\xda\xed\x6f\xa5\xc6\x43\x9b\x3d\x86\xa8\x54\x35\x22\xc3\xf8\xf3\x71\xd2\xd9\xc2\x9a\x9b\x3c\x00\x57\x65\xe5\x35\xe1\x3b\x02\x72\x13\x16\x88\x80\x8d\x25\xd4\x45\x15\x3a\xc6\x32\x46\x68\x6c\x8c\xc2\xe1\x68\x06\x1c\xf2\x86\x51\x3a\x9b\xd8\xde\xb2\x8b\x0c\xe4\xb2\x6c\xaa\xca\x05\xc5\x41\x7c\x86\xc0\x5f\x73\xaa\x22\xe6\x36\xc7\x49\x0b\x32\x26\xab\x47\xb0\xd4\x1d\x1d\xf3\x81\x18\x61\x3a\xe6\x43\x63\x35\xea\x27\x48\x03\x2f\xb7\x1a\xee\xc2\xc2\xb4\xaf\x0f\x5a\x4b\x0d\x77\x32\x29\x7f\x7e\x19\x1f\x86\xc3\x60\x6e\xc7\x1f\xc0\xbc\x73\x86\xf9\x42\x86\x35\xb8\xaa\x4f\x82\xba\x2f\xec\x23\x3f\x9d\xdb\x3a\x8e\x23\xc8\xd0\x2d\x52\x5a\x0b\x0b\x0d\x43\xbe\xe1\xd5\x59\xfc\xea\x01\xb0\xaf\x38\x00\x7e\xf0\x19\x72\x51\xd6\x0e\x50\x4c\xd5\x7a\x7c\xa2\x20\x92\xd5\x60\xe1\x30\x20\x04\x23\xe8\x2b\x38\xa0\xac\xc3\xc7\x11\x5f\xe0\xfd\x86\x59\x7d\x2e\x8e\xb0\x36\xef\x68\xa1\x4a\x5b\xa3\xbe\x68\x0f\x17\x8a\x98\x83\x4e\xfa\xb2\xdd\xf1\x1f\x1a\xb3\x69\x7d\x4f\xf8\x88\x90\x44\xd2\xbc\xdf\xf5\xf7\x45\x58\x88\xbc\xae\x1a\x8f\x5c\x37\xb7\xee\x03\xa4\x26\x7d\x68\xa2\x5e\xa7\x50\x47\xbc\x8b\x06\x7c\xfb\x32\xe2\x5f\x83\xa3\xaa\x58\xf3\x5f\xd6\x08\x3a\xf3\xb1\xb0\x08\x0c\xce\x9c\x16\x77\x50\xda\xfb\x12\xfd\xd0\x7f\x59\xc3\xe2\xb6\xc8\x42\x13\xbe\xd0\x10\x84\xf7\x28\xb2\x62\xe1\x38\x5c\x99\x5c\x5e\x22\xe8\xb3\x17\x5e\x73\x4b\x9c\xd9\xfb\x92\xd8\xfb\x79\x65\xde\x97\x48\x66\x7d\x59\xc3\xa8\xb6\xda\x1e\x2b\xfd\xac\x50\x5e\xf5\x83\x61\x78\x12\xa2\x8e\x64\x63\xa1\x21\xfa\xa4\x36\xf9\xa5\xa0\x70\x8a\x2f\xf0\x03\xea\x51\x99\x78\x4b\xfc\xa6\x1d\xdc\xbf\xee\x84\x1c\x07\xf2\x2d\x42\xb9\xb2\xc3\xc9\x1c\x85\xc4\xb8\x84\xc8\x53\x22\x3e\x1b\x6a\x97\xa8\xc6\x74\x8c\x1a\x53\x29\x1c\xa8\xf6\xbd\xa5\x2e\xf3\xa1\xbc\xf2\x57\x0a\x78\x0f\x1b\xc1\x2c\x9c\xbf\x12\x03\x92\x10\xf3\xa0\x52\x19\xfe\xff\xdc\xbd\x7d\x57\xdb\x48\xb6\x37\xfa\xff\xf9\x14\xa0\x7b\x16\x23\x1d\x2a\x0e\x4e\x77\xa7\x3b\x72\x2b\x2c\x02\x64\x9a\x3b\x21\xe4\x02\x99\x3e\xcf\x65\x38\xb4\xb0\x65\xac\x89\x2d\xb9\x25\x9b\x84\x01\x7f\xf7\xbb\x5f\xea\x55\x2a\x19\xe8\x99\x67\x3d\xb3\xee\x1f\x60\xa9\xaa\x54\xef\xb5\x6b\xd7\xae\xbd\x7f\x1b\x3d\x5c\x2e\x13\x5a\x97\xb5\x59\x5c\x97\x09\xac\x28\xeb\x1d\x5e\xe3\x46\xf4\x76\x1f\xed\x26\xe8\xc3\x65\x54\x5c\x54\x3d\x96\x42\x84\x75\x04\xb1\x81\xb1\x58\x1a\x26\x26\x4a\x7b\x07\x5d\x46\x28\x4c\x6d\x45\x2c\xb7\xfb\x6c\x49\x2d\x27\xa3\x39\x2c\x34\xb4\x8a\x86\x51\x84\xa6\xc1\x79\xb1\xcc\x06\xc5\xc5\x10\xe6\x60\x3b\xc5\xee\xc5\x25\xf2\xd2\x40\x58\x43\x4c\x12\xa9\x17\xf4\xf0\xa4\xd9\xe2\x62\x25\xe4\x78\x70\x91\x2d\x17\x00\x78\x80\x50\xa6\xa5\xca\xb0\x3b\x53\x42\x0a\x86\x64\x25\x16\xf9\x7e\x85\xf5\x0e\x2e\x2e\xf1\x9e\xa0\x8a\x4a\xe4\x4f\xd1\x1f\xaa\x2c\xd4\x29\x44\x59\x1c\x99\x4e\x4a\x93\xe0\x82\x3e\xbc\xd8\xb9\x04\xd2\xc5\x99\x5c\x54\x66\x9b\xdc\xad\x64\x17\xe1\x09\x41\x85\x46\x30\xb5\xeb\x84\x32\x3e\x2a\x16\x61\x2a\xfa\x3b\xc8\x5e\x07\xc1\x76\x3d\xd8\xcc\xeb\x8f\xe9\x47\x18\x8d\xad\x2d\xb4\x6d\x49\xb7\xb6\x96\x09\xfd\xd4\x6f\x93\x1d\xf8\xff\x33\x74\x99\x99\xab\xbb\x21\x57\x18\xd6\x71\xe2\xad\x6a\x5c\x02\x95\xf0\x46\x99\x65\xaf\x7a\xf2\x2f\x40\x42\x7c\xfd\xb8\x50\x2b\xe9\xe5\xff\x84\x17\xff\x83\x7e\x83\x2f\xff\x2b\x7a\x09\xbd\xf4\x32\xfc\xdb\x85\x0a\xf8\xdb\x65\xf4\xf2\x06\x3d\x73\xc2\x4a\xce\xd0\xa0\x94\x5c\xe2\x3e\x36\x1f\x52\xf4\xa9\xaa\xe6\xf4\xc5\xe5\x00\xdf\xa1\x91\xcc\x0a\x52\xa4\x26\x64\x4b\x3c\x9d\x31\xa6\x47\x98\xc2\x00\xc9\x62\xa0\x9f\x96\x3f\x17\x3d\x5a\xc6\x83\x68\x7b\x7b\x29\x9e\x52\xa6\xe5\x4b\xf8\xe2\xe1\x6f\xe8\xd4\x38\x08\xa2\x08\xaf\x76\xac\x92\x95\x19\xbe\xae\x10\x8c\xf5\xf6\x42\x8e\x67\xca\xab\x2a\xda\x86\x41\x8f\xdc\xb9\x18\xd6\xd2\x73\x87\x6d\x89\xde\x3a\xde\x06\x74\x31\xc5\x1e\x7f\xf8\x29\x30\xdb\x89\x66\x41\x16\x72\xee\xc2\x34\x55\x6e\xf9\x2c\xa2\x92\xb4\x5d\xf4\x99\x48\xb4\x4e\x45\x5d\x4a\x72\x3c\x6d\x85\x47\xbb\xd6\x4b\x9c\x3b\x24\x8a\xba\x31\x09\x58\x41\xdd\xcd\x15\x22\x76\xe5\x2f\x7d\x04\xbf\xf0\x81\x99\x8a\xbe\xaf\xac\x89\x6a\xbf\xc0\xf7\xe6\xa5\x4d\x18\x3d\x19\xb9\x29\x76\x9b\x01\x71\xde\x08\x18\x18\x82\xdc\xea\xa2\xc5\xae\x43\xc9\x69\x40\x80\x95\x43\x52\x00\xf3\xd7\xde\x4e\x8b\x48\xba\xaa\x57\x82\xe3\x81\xf2\x50\x2f\x29\x64\x8a\x4e\xea\xa7\x89\xb5\x7e\xc2\xa1\x40\xa2\x05\x59\x0e\x60\x33\xef\xcd\xb2\x0a\xb8\xf0\x52\x4c\xf5\x72\x43\x39\xc1\x6c\x0e\x8c\x6b\x58\x46\x72\x5f\xe3\xbd\x29\xfe\xe1\x7b\xdc\xc6\x3c\xd7\x23\x4f\xd9\xc6\xa8\x3f\x3f\x55\x30\x7d\xbe\xfd\x19\x0f\x67\xc8\x02\xd6\xf1\xbd\xf2\x0b\xdc\xe1\x52\x7b\x1b\xe9\x1e\x7a\x9c\x1e\xc1\x94\x5e\x93\x28\xd8\xce\x70\x9e\x93\x38\x16\xd8\xd4\x8e\x84\xe8\x2d\x22\x37\x4e\x8a\x7d\xa4\x04\x67\xe4\xbb\xe5\x78\x8c\x8e\x41\xd0\x24\x03\xad\x12\xa5\x95\x3a\x8c\x81\x2d\xee\x39\x00\x06\x50\x26\x38\x3a\x3b\xd1\x69\xd4\x6a\x21\x43\xe2\x00\x9d\xaf\xb7\x86\x17\x16\x52\x73\x02\x61\x18\x82\x45\x65\x69\xd1\x5e\x5a\x17\x59\x21\xc5\xf0\x06\x4a\x25\x83\x75\x9d\x40\xab\xdb\x31\x8b\xe8\x52\x3a\x93\x04\x72\x85\xcb\x78\xcd\xa2\xdd\x28\xf5\x3c\x74\x27\xd6\xe2\x29\x13\x6b\x60\x6d\x43\xcd\xeb\xfc\x5d\xab\x9f\xc3\x05\x4e\x38\x14\x10\x0d\xd1\xbc\x37\x6e\x45\x65\x34\x82\x43\x1c\x41\x32\x64\x31\x84\xbf\x8b\x3c\xb9\x7e\xc6\x7d\x4d\xb4\x48\xc8\xae\x45\x42\x62\x9b\xe3\xa9\x54\x17\x31\x7a\xab\x41\x67\xb2\xa8\x9e\x76\x30\xce\x9d\x3a\x40\x1f\x9d\x96\x67\x6b\xd4\x4f\x96\xc4\xa2\x39\xb9\x77\x9d\x84\x71\x20\x27\x31\x1e\x1a\x32\x88\x93\xaf\xbb\x3a\x9c\x04\x03\x30\x79\x03\x93\xd4\x1a\x9d\x8e\x42\x90\xcb\xaa\x9b\x43\x07\x3b\x91\x18\xea\xeb\xaf\xc1\xf0\xed\x12\x86\x6e\xc9\x43\x37\x4d\xea\x8b\xe5\xe5\xa0\x4a\x2a\xc3\x41\xd8\xc3\x31\x05\x7a\x21\xd2\xc8\x22\x07\xe4\xbe\xb3\xf0\xd2\x02\xcf\x95\x8b\xdc\xfc\xcf\xcb\x16\xdb\xe3\x48\xa4\xb4\xc0\xa9\x29\x63\xb2\xc6\xd2\x0c\xc7\x45\x71\x89\x3a\xd8\xf0\x93\x10\x74\x84\xd6\x7e\x86\x6c\x98\x84\x79\xa4\xb3\x1a\x2e\x67\xe1\x1d\x63\x1d\xdd\x9a\xba\x0b\xe5\x10\x37\x46\x07\xdd\x28\x29\xf5\xe7\xa0\x57\xd1\x22\xb9\x58\x68\x96\x10\x08\x6b\x5b\xb7\x65\xb3\xe1\x46\x9e\x71\x06\x1a\x7d\x85\xcc\x82\xd1\x7c\x77\x06\x15\xdd\x13\x41\x7f\x21\xc5\x96\xfd\x55\xbe\xcd\xa1\xbf\xf2\x48\x72\x79\x15\x7a\x61\xaa\x93\x0c\x98\xa9\xc1\x02\x39\x2a\xfc\xb7\x2b\x3b\x27\xc4\x17\x51\x03\xa7\xbd\xd2\xa4\x50\x14\x92\x47\x76\x46\x88\x9c\x3b\x35\xee\xfe\x2c\xd2\x62\x71\x25\xdb\xc8\x92\x6c\xa0\x55\x08\xfb\x47\x72\xc8\x2c\xea\xa6\xf1\x26\xe2\x61\x2b\x1e\x5f\x6c\x30\x62\x19\xcb\x66\x25\x3f\x9c\x59\x9e\x20\xf9\x70\x80\xee\x21\x35\xd7\x7c\x51\xd1\x32\xd6\xba\xdf\xa2\x39\x00\x66\xea\xe5\xcc\x3e\xe3\xc9\x65\xd1\x3c\xb9\xf8\xa7\x5e\x09\x53\x2f\x97\x39\xc3\x8b\x9e\x7b\xb9\xd4\x2e\x77\xd7\x1e\x8d\x1f\xe7\x5f\x7b\x4f\x46\xcb\x04\xd7\x2c\x8c\xd1\x12\xcf\x16\x6a\xab\xc5\x57\x14\xa1\xda\xc3\xa3\x58\x23\x67\x80\x24\x35\xba\xe0\x4e\xdc\xe0\x14\xc4\xd5\xb7\xb8\x4a\xb5\x71\x49\x21\x6d\xc4\x79\xf2\xe6\xe6\xc9\x73\xe3\x11\x3e\x6f\x77\xb3\x1f\x93\x37\x09\x0b\x2b\x0e\x95\xb6\x6c\x60\x45\x95\x7d\x57\x38\x0e\x85\x3a\xc4\x3f\xc3\x61\xe0\xb8\x1c\x2e\xeb\x8f\x30\x1b\x95\xc3\xc0\xc7\x1c\x40\x4a\x94\xf7\xe5\xa2\x7c\x8f\x9f\x12\xec\xbe\x94\x7e\x1f\x9c\x1c\x63\x4e\x08\x28\xe0\x71\x5c\x67\x4a\x8a\xfb\x3f\xd2\xa9\xfd\x19\x9e\xeb\x94\x88\x4b\x8a\x84\x90\x9b\x4f\x95\x96\x97\x9c\xf4\xa6\x3b\xe1\x30\xd6\x96\xe7\x2d\x7a\xb7\x59\x85\x68\x7f\x5b\x5b\xfa\xf0\xa5\xc3\xe0\x34\x08\xc7\xb0\x9f\x93\xfe\x2b\xaf\x5e\x5d\xe8\xb8\xf4\x30\x7e\x3e\xa4\xf3\x0f\x24\x42\x26\x09\x01\xe0\x4d\xd9\xe7\x87\x6b\x9b\x22\x7d\x79\x2d\xa4\x2f\xaf\x13\x98\x46\x73\xa2\x00\xac\x87\x7f\xb6\x48\xab\x45\x2c\x67\xcc\x39\xcd\x5f\x3b\x66\xe0\xfd\xe8\xb0\x18\x79\x3f\x81\x70\xff\x07\xd2\x47\xa7\xef\x1b\x8e\x5a\x75\x22\x1f\xe1\x4a\xc0\xdc\xa0\x69\x07\xe5\xd7\x02\x2d\x42\x60\x69\xee\x23\xa1\x4b\x92\xc3\x16\xe4\x91\xaf\xb9\xf0\xe9\xe7\x79\xac\x84\x92\x40\x69\xae\x35\xf9\xd1\x99\x45\x03\x27\x3d\x16\xa5\xaa\xab\xd3\xc0\x97\x87\x6e\xb2\x4f\x08\xe6\x18\x9b\x20\x98\xbd\x75\x46\xdf\x9a\xb0\x77\xd3\x65\x15\x2b\x08\xa4\x81\x34\xfe\x51\x01\xfd\x95\x03\xb2\x64\x4c\x86\x46\x30\xca\xf9\xb4\x6b\xb6\x65\x30\xdb\xa0\xdb\x52\xc5\x7b\xe0\x33\x9b\xa5\xea\xdc\x86\xc6\x71\x20\xd1\x49\x31\x44\x92\xfa\x6d\x37\x27\xcb\x9a\xf8\xd3\x2e\x76\x58\x85\xfb\x56\x9e\x34\x07\x31\x8a\xd3\x8e\x48\x9a\x14\xe8\xfc\xc2\x81\xae\x3b\x85\x84\x9f\x1e\x1e\x72\xe8\xa0\x76\x6a\x28\x31\x69\x95\xb0\xb5\xf5\x09\xbe\x19\x26\x9f\x68\x09\x43\xed\x61\xfd\xc6\x9f\x92\x19\xbe\x7e\x42\xbe\x79\x04\x1b\x90\xf2\x16\x7e\x63\x85\xe6\xd4\x24\x6c\xca\x30\x9a\x52\xbb\x93\xa1\x91\x8e\xcc\x93\x25\x02\x6e\xc8\x53\xfb\x9c\x3c\x81\x53\x9a\xb9\x26\xc5\xa3\x5e\x3a\x1c\x2e\x67\xcb\x29\xcc\xba\xf3\xaf\xe5\x27\x38\xab\x67\x07\x12\x10\x00\xce\x66\xd3\x48\x58\x9d\x38\xed\x9e\x54\xfe\xe5\xb0\x0c\x9b\x33\x89\xa7\x08\xf3\xb5\x59\xef\xeb\x24\x1f\x4e\xb4\x1d\x1a\x22\x66\xed\x62\x65\xe3\xf0\x08\xd9\x92\x63\xfb\xdb\xf3\xec\xdb\xe2\xa8\x98\x2f\x17\xb1\xda\x33\xb1\x25\x36\x32\xce\xf1\xd6\xd6\x11\x7f\x5e\x35\xe6\xd5\x06\x9b\x28\xeb\x76\xcc\xf5\x6e\xfd\x89\x05\x2c\x6a\x55\xb9\xad\x78\x78\xe0\x55\xc4\x53\xa6\xb0\x47\x47\x95\x3b\x03\x96\x01\x4e\x35\x75\x06\x39\x89\x4f\x12\x10\x62\x65\x97\xea\xeb\xac\x4f\x69\x6d\x96\x3f\x4d\x19\x4f\x1f\xe9\xe5\x46\x9d\x04\xe4\x2d\x87\xce\xdc\x95\x7b\x1e\xa2\x72\xec\x4f\xd2\x0a\xd7\x61\x28\x93\xf0\xe1\xec\x51\x12\x75\xca\x7d\x24\xfb\x6f\x7d\x47\x8d\x1b\xab\x86\x1c\xca\x27\xfb\xbb\x53\x5a\x0f\xf1\x9c\x7e\x9a\xd3\x9f\x4f\x67\x77\xd6\x2c\x3d\xef\x5d\x67\xc0\x38\x64\x34\x7e\x3c\x63\xd5\x19\x88\xe7\x63\x2e\x1e\x99\x87\x65\x24\x4a\x62\x48\xa4\x25\x19\xe9\xa7\xed\x97\x74\x5c\x5d\xe0\x81\x7c\x64\x85\xa3\xa4\x29\xa5\x4b\x18\xcb\x88\xdb\x6f\xad\xa4\x0c\xb7\xdf\x03\x0f\x81\x4a\x4b\xee\x56\x40\xc6\x18\xd2\x74\xfb\xec\xae\x58\x4c\xb2\x45\x3e\xb4\x7b\xf5\x96\x33\xb9\x6b\x24\xa1\x76\xaa\x48\x69\xb4\x0d\x44\xf3\x64\x4c\x16\xda\x17\x6f\x44\xff\x3b\xf1\xea\x47\xf1\xdd\xab\x4b\x71\x98\xbc\x7a\xf5\x46\x7c\x4b\x6e\x8d\xdd\x14\x10\xb3\x56\x19\xfa\x26\x46\x7c\x65\x24\x37\x37\xbd\xb2\xe9\x3a\xc6\xad\x1d\xd2\xaa\x77\x54\x0d\x4c\x5a\x96\x5f\xc7\x44\xe0\xb1\x37\xf7\x1b\xe5\xe2\x22\x6b\x14\x08\x13\x0f\xff\x60\xfb\x17\xa7\x6e\xea\x70\xf3\xdb\xc3\x03\xc4\x7d\x7d\xfb\xd3\xd6\x56\xbf\xff\x36\xf9\x8a\xf6\xde\xdf\xbd\x12\xc7\x89\x6f\x96\x9e\xa1\x99\xf7\x04\xe7\xe5\x87\xec\x36\x9b\xb2\xd9\xe6\x79\x72\x6f\x4d\x8d\xf8\x7e\x8e\xe3\x3e\x02\xb6\x2f\x07\x06\x84\x6e\xf6\x08\x12\x31\xbe\xbf\x5e\x5e\x5f\xc3\x54\x8a\xaf\xc2\xfb\xb2\x78\x67\x7d\x42\x33\x36\x12\xc3\x74\x0e\x13\xca\x93\x60\x9f\x23\x64\xba\x15\xde\x37\x20\x16\x42\x31\xcc\x21\xdb\x0b\xcf\x3a\x11\xce\x32\x14\x2e\xf1\x11\x66\xfd\x5e\x4a\xfc\x05\xb3\xc0\x9e\x58\xfb\xc6\xb2\xf4\x36\xc0\x4d\xf3\x84\x36\xe0\xb6\x2a\xd6\xb5\x06\xb7\x61\x5f\xd3\x88\x1b\x10\xee\x76\xed\x36\x8d\x79\xa2\xe7\x37\x8e\xbf\x7b\xac\x79\x94\xea\x8f\x36\x90\x3e\xfe\x17\x34\x51\x32\x64\xcf\x6f\xa3\xfc\xf0\xb1\x46\x72\xb2\x3f\xda\x4a\xfe\xfa\x0f\x36\x73\x25\x8e\x50\x23\x5a\xee\x4d\x07\xc9\x3d\x79\xdb\x62\x54\x94\x73\x01\xf3\xba\x82\x03\x1a\xad\x79\x57\xfe\x68\x6b\x3b\x5d\x18\xee\x49\x98\x2d\xe1\xd2\x39\x61\x1c\xf0\x09\xa3\x41\x98\xe3\xd7\x64\x29\xd4\x22\xcb\xf1\x8f\x64\x02\xd4\x6d\x08\xba\x86\x24\xc7\x3f\x92\xf5\x4f\x37\x41\x8e\xfb\xdf\xff\x28\x3a\xe8\x71\xdc\xff\x81\xac\xaf\x98\x1c\xc7\xfd\x37\xe8\xdf\xe2\x87\xe7\x69\x2b\x58\xa2\xd9\xcc\x18\xb6\x40\xbf\x7f\x46\x2c\xdb\x7d\xe4\x06\x22\x88\xa9\x97\xd7\x2c\x79\x0a\xfb\x4a\x57\xf4\xfe\xba\xfc\xf6\x7e\x9a\x7d\x43\x90\x71\xf9\xf8\xe7\xaa\x5c\xce\x19\x74\x7c\xba\x9c\xc1\xa4\xc1\x03\x1f\xbc\x8e\x65\xb2\x31\xa7\xf9\xaa\x9e\x19\x49\xed\x36\x53\xef\x67\x13\x28\xe2\x8b\x7a\xfb\x98\xa1\xa9\x9b\x8c\x2d\x8b\xc5\xaf\x19\xba\x97\xc6\xb7\x29\x9c\x77\xf7\xa7\xe9\x6c\xae\x5e\x7e\xd1\x51\x30\x2c\xc3\x7c\x71\x47\x8f\x15\xc2\xc4\xd0\x03\xac\x85\xa2\xc6\xc7\xaf\x39\xea\x0b\xe0\xd3\x3f\x8e\xf0\x9c\x40\x4f\x65\x39\xa3\x32\xf2\xe9\xf4\xc4\x7c\x0e\xed\x2d\xbf\x64\x07\x69\x3d\x29\xc9\xec\xd8\x84\xb5\x12\xfd\x9a\x8f\x16\x13\x04\x57\x17\x65\x72\x11\xfc\x9a\x5d\x7f\xc9\x17\x81\x08\x66\x35\xfc\x3b\x2e\xff\x01\xff\x4f\x82\xcb\x81\x2d\x7d\xc8\x23\xaf\x91\x41\xd9\x0e\x45\xde\xee\xa2\x22\x8c\xf3\xcb\x24\x47\xec\xa6\x68\xa5\x70\xe7\xee\x71\x4e\xdd\x54\x68\x57\x17\x5b\xcf\x47\xb3\xf4\x86\x7a\xcd\x04\x69\xa7\xc8\x4e\xe8\x29\x4b\xe0\x9d\xb0\xfd\x72\x5a\x56\xd4\x96\x6b\xee\xc0\x7b\xfe\x55\x6d\x94\xc1\xec\x4c\x4b\xbf\x36\xbf\x7a\x57\x2e\x16\xd0\xab\xf7\xf6\x5b\x23\x07\x0e\x6c\xe4\xc3\x81\xcd\xdc\xd0\x14\x5c\xe5\x85\xcf\x8d\x9c\x30\xa8\x91\x0f\x06\x35\x73\x21\xef\xe4\x2a\x1b\x7a\x69\xe4\x43\x61\x8d\x8c\x28\xac\x99\xd3\x79\x39\x57\xf9\xc0\x63\x23\x17\x08\x69\xe4\x71\x8e\x14\x50\xe5\x80\x33\x39\xbe\xc7\xff\x3a\x15\xbe\xfc\x95\x75\x8e\xda\x73\x9d\x52\xe6\xff\xc8\xda\x53\x1d\x63\xde\xa7\xb3\x7c\x7a\x47\xb8\xfe\xa2\x4e\xee\xf3\xfa\x73\x91\x2f\xa6\x40\x46\x3f\xd2\xad\x45\x9c\x0b\x98\xbe\x15\x82\x19\x8f\xd4\x9d\xe5\xe1\xb7\x39\x42\x5e\x00\x59\x8b\xd3\x55\xc3\x73\x2f\xd2\x8f\xa7\x7b\x23\x7f\xb9\x7f\x76\xa6\x72\x35\x6a\x18\x1d\xcc\x69\x99\x84\xac\xbb\x04\x9b\xd0\x14\xda\x43\xad\x27\xff\x81\x91\xa0\x88\x11\x2a\x99\xc1\x14\xac\x29\x86\xee\xd3\x82\x48\xfb\x27\x9a\xdc\xcd\x27\x59\x81\x4e\xbe\xad\xef\xa4\x06\xc9\x2c\x9b\x95\x94\x23\x12\xa8\x93\x62\xca\x0a\xa6\x5c\x9c\xc1\x85\xa8\x7d\x18\xcb\x29\xc1\x4f\xa0\x11\x5d\x30\xac\xeb\xf7\xd3\x32\x85\x16\xe6\x36\x67\xc8\x3a\x15\x08\x06\xd9\x09\x3a\x80\x35\xea\xa9\xcf\xe9\xec\x1b\x50\x18\x67\xa7\x8e\xba\xf7\xac\x95\x75\x9c\x56\x5f\x96\xf3\xf7\x25\xaf\x20\x17\x78\x96\x25\x04\x81\xb9\x4b\x20\xc4\xe1\x05\x62\xaa\x2c\xda\xb8\xde\xfa\x32\x0f\x15\x8a\xf9\x5c\x8c\xca\xc1\xd9\x36\x9c\x94\x8b\x68\x3b\x88\x03\x01\xcf\x25\xc2\xad\xc0\xdb\x20\xd0\xe7\xe4\x8c\xa5\xb8\x04\x02\x47\xfd\xec\xab\x0d\x6e\x0d\x7c\x54\x94\x2d\xd4\x95\xca\xbb\x81\x5e\xf2\x48\x09\xb9\x4b\x38\xce\x67\x17\xf9\x25\x9d\xe7\x83\x31\xf5\x04\x74\x62\x4e\x72\x87\x21\x0c\x6b\x54\x40\x6c\x92\x9a\x03\x7e\x9d\x54\xbd\x35\x93\x15\x52\x63\x56\x75\xa4\xef\xf0\x09\x54\x19\xb2\x59\x6a\x5d\x93\x0d\xca\x33\x08\x56\xae\xaf\xf9\xa9\x44\x43\xb2\x66\x6b\xfc\xc3\x8f\x8f\xed\xd9\xed\x89\x1a\xf7\x5f\x93\xba\x90\x6f\xa6\x42\x1c\xe5\xe8\x99\xa7\x71\xff\x27\x8a\x6a\x4f\x53\xd8\xb2\x29\xa6\x01\xce\xf1\xc3\xb3\xc0\x39\x58\x53\x73\x28\x39\x8c\x9a\x79\x23\x19\xc8\x28\x6f\x1c\x66\x2b\x10\xf2\x59\x96\xb0\xa1\x15\x16\x46\xaf\x85\xb0\x22\x57\x9e\xa5\xea\x3d\x28\x11\xf2\xd6\xb8\x22\xc9\x8a\xdf\x97\xd9\x32\x6b\xcc\x9a\x66\x85\x1a\xef\x46\x8f\xdb\xd4\xcf\x7d\xb5\x53\xa8\xaf\x1a\x0a\xbd\x2a\xa9\xba\xfe\x59\x09\x56\x55\xdd\x9b\x4e\x3b\xfc\x16\x98\xac\x44\xd6\x28\x6f\xc0\x7a\x29\x40\x0b\x94\x32\x77\x92\x28\xcd\xfd\xa8\x59\x91\xce\xfe\xb5\xd4\x04\x5a\xb7\x65\xa8\xfe\xbf\xd0\x4a\xd8\x84\xa1\x3e\xd0\x85\xed\x88\x4c\x3f\x22\xe8\x67\x56\x67\x6d\x31\xf9\x53\x06\x18\x98\x70\xed\x19\xa6\xf9\x3d\xe5\x1a\x46\xe8\xfe\x25\x47\xdb\x3a\x9c\x01\x88\x76\x09\x23\x1a\x89\x96\x02\xa9\x07\x4a\xc6\x9d\x34\xf1\x4f\xc4\x79\xb6\x74\x65\x5f\x3f\x06\x6c\xe2\x33\x4c\x0f\xce\x0e\x3f\x1c\xee\x9f\xb3\x71\x75\x01\xe7\x6b\x5c\x36\x0f\x0f\xc1\xd1\xc7\x4f\x9f\x1b\xa1\x28\x8a\xcf\xa7\x19\x07\xe2\x24\xf4\x02\x44\x7d\xb5\xe4\x35\x27\x3d\xb6\xdd\x15\x47\x88\x39\x75\xbd\x5e\x34\x93\x45\xe2\x5b\xef\x9a\x5e\xa4\x37\x96\x3a\x2c\x1d\xf0\x7e\x12\xbc\x5f\xf5\xe4\xcc\xe7\xb3\x06\x4e\xcb\xab\x9e\x84\xef\xa2\xa0\xff\x07\x23\xc3\x36\xe6\xff\x79\xb2\x80\x23\x4c\x26\xce\x9b\xe6\x95\xca\xbe\x38\x77\x90\xfe\xe1\x03\xa0\x97\xe7\x24\x31\xf6\x26\x16\xe7\x3c\x1b\x8e\x24\x02\xbb\x2d\x70\x76\x00\x2c\x51\x2a\x78\x4c\x47\x31\xfa\x76\xb7\x60\x34\xdb\x9d\x96\x50\x99\xcd\xee\x29\x29\xdd\xc7\xec\x86\x08\x7a\x88\x4e\x97\x51\x01\x4c\xc7\xe1\xd9\x0e\xc1\x2e\xa3\x96\x40\x55\x35\xf1\x13\x0c\x10\x29\x71\xc3\x39\x4d\x4e\x27\x18\x14\x6b\xb3\x38\xc8\xd8\xf9\x07\xac\x1a\xf7\x06\xca\x10\x18\x69\xf5\xd2\x65\xe1\x72\xae\x12\x88\xbd\xa8\xdd\xa5\x73\x99\x4c\xf5\xd6\x38\xb2\x85\xa6\xdc\xb5\xa3\x6c\x9a\x2d\xb2\x8d\x73\x59\xd3\x56\x4f\xb7\xf3\x70\x7b\xdc\x1c\x45\x1b\xfd\x3f\x96\xda\xc1\xb2\x82\x34\x5d\x55\x66\xe4\xc6\x58\xdf\x06\xd4\xd5\x50\x31\x12\x94\x76\x80\x77\x11\x28\x41\xff\x04\x9d\x98\xf3\x2d\x9c\xce\x76\xd2\x35\xac\x74\x2a\xf4\x8c\xea\xa8\x6b\x54\x51\xff\x7f\xea\x1f\xd5\xb9\x3d\xaa\xb7\xcd\x12\x37\x65\xda\x33\xe8\x3a\x4a\xc2\x33\x6a\x6b\x4b\xc7\xd0\xd9\xdd\x7d\xc7\xe3\xfb\xc3\xc3\xe6\xf9\xc3\x83\xec\x6a\x28\xf1\x93\x52\x57\x85\x96\xaa\x01\x38\xb2\x4a\x9e\x59\x04\xc2\x4b\x09\xc2\x00\x96\xe9\xf0\x0b\x9c\x3d\x0d\x39\x00\xaa\x51\xa5\xa3\xbc\x34\x21\x56\x8e\x37\x9d\x8b\x02\x1d\x01\x9b\xde\x63\xd0\x69\xbf\x6c\xf6\xca\x96\xcd\x4e\x97\x37\x79\xf1\xcb\xf2\xda\x80\x55\x7a\x64\xb6\x87\x6b\xd9\xe2\x6f\x0a\x66\x32\x1d\x2e\x24\xc5\x31\x18\x95\xfa\xd0\xaf\xe4\xaf\xfb\x0a\xd4\x92\x02\xce\x18\x45\x10\x35\xc6\x15\x5c\x65\x5e\x6b\xf1\x9e\x9c\x55\x06\xb8\x52\x49\x6d\x8f\x93\xbb\x86\xe4\xf2\x04\x98\x53\x86\x5d\x7f\x5c\x6a\x74\x46\xe2\x20\x4e\xdd\x14\x15\x59\x71\xeb\xe5\x43\x7a\xb6\x09\x8b\x28\x09\x33\x16\xc2\x4c\x55\x61\xe6\xb7\xb0\xa7\x93\x30\x73\x4d\xf8\x26\x24\x4a\x8b\xd6\xac\x55\xf1\x25\xd9\xec\x0f\x0e\x1d\x19\xf0\x97\x64\x1f\xe7\x14\x2d\x75\xbc\x20\xdb\x0c\x3b\x85\xd1\x91\x07\x84\x0c\xd3\xbc\xfd\x49\x5e\x6d\x7d\x6c\x67\xff\x11\xb3\xcf\xb1\x21\x7f\x38\xf7\x37\x32\xf7\xbd\xe4\xde\x6b\xbf\xb6\x71\x80\x44\xd6\x98\x7a\x45\xc4\xe3\x3b\x67\x8c\x4f\xa8\x1a\xbc\x10\x07\x88\xbf\x6b\xc3\x87\xe2\x65\xff\x07\x47\xa2\x76\xb2\x5e\xa2\x26\xf5\x59\x4a\x91\x12\x76\x3e\x5e\xe8\x7c\xd9\x2d\x93\x65\x9c\x26\xc3\xf8\x14\x5f\x3f\xc2\xeb\x24\x0e\xcb\xe4\x16\x78\xc9\x51\x14\xcf\x58\x99\xa6\x4c\x6e\x80\xe7\x54\x8a\xba\xa5\x72\xe6\x40\xcc\xbd\xd4\x7b\xf2\x6e\xe0\x35\x14\xa9\xee\x5a\x1e\xd9\xc7\xe9\xaa\x6f\x95\x22\x7a\xa1\x54\x50\xb6\xcf\x03\x1f\x1e\x17\xef\xe9\x95\x1d\xff\xb8\xf3\x47\x85\x7e\xce\x9a\x8e\xfb\x8c\x3c\xda\x58\xd2\x10\xfc\x46\xf8\x56\x34\x1c\x0d\x76\x84\x7f\x41\x43\xd4\xab\x96\xd8\xef\xf5\x63\x88\x40\x7c\x56\xdc\x21\xa5\x0c\x89\x70\x05\xd5\x3b\x2d\xcb\x05\x0b\xc2\xda\x73\xa9\xda\xde\x6e\xe9\x5d\x60\x49\xcf\x41\xf1\x91\x9b\x4f\x2f\x2f\x6a\xd8\xfa\xf8\x2a\x03\x65\x59\x0c\x29\x89\xda\x1b\x68\x9b\xc8\xe7\xd1\xc8\x3e\xa1\x1c\xd0\x19\xcb\x1c\x4e\xa8\xb6\xc7\xcb\xe9\x22\x27\xe4\x26\xee\xd6\x86\x0f\x63\x98\xd1\xd8\x59\x84\x6d\x5d\x58\x7e\x0c\x5d\x97\xaa\xf7\xfa\xf8\x36\xbd\x3b\x65\x1d\x29\xac\x07\xba\x14\xe0\xb3\x39\x6a\x24\x3f\x92\x44\xb0\xd1\x9c\x55\x5a\x9c\x0a\xc9\x00\xca\x11\x6f\x1c\x8a\x8c\x65\xce\x92\xe9\xcf\x90\x7f\xa6\xc9\xce\x60\xfa\xb3\x3e\x2c\x4c\xe1\xa0\x80\x46\x45\x09\x69\xf7\x15\xb4\x83\xc1\x2e\x55\xf6\x8e\x4f\xfe\x7a\x78\x75\xf8\xdf\x47\x67\xe7\x47\x1f\xff\x0c\xfd\x65\x62\x4e\x0f\x29\x0e\x3d\x19\x45\xf2\xa6\xbc\xa0\xdb\x2a\x1a\x57\x31\x4e\x10\x01\x02\xcd\xf4\xb0\x09\x76\xbf\xcf\x2f\xc5\x44\x47\x1e\x1d\x0c\xea\x70\x8c\xfd\xb3\x24\xc5\xf0\xe5\xc5\xe4\x32\xc1\x7f\x74\x18\xc3\x07\x48\x9f\x8c\xa1\xda\x43\x0a\x91\x50\x42\x63\x1e\xb4\x51\xd2\xe8\x33\x44\xe8\xe6\xae\xc2\x5b\x73\xba\xd2\x57\x3d\x70\x0b\x2d\xbe\xfd\x59\xc1\xf7\x0c\x6e\xa1\xc5\xc3\x8b\xdb\x4b\xbb\x92\xca\xa2\x14\xaa\x1a\x62\x9c\x51\xb5\x9b\xc1\xc7\x33\xd3\x5d\x33\xf8\x58\x5e\x4a\x63\x97\xcd\x54\x97\xc9\x0b\xea\xb2\x77\xf4\xf1\xec\xf0\xf4\xfc\xea\x78\xef\xf4\x2f\x9f\x3f\xc5\x55\x68\xf7\x85\x18\x5d\x14\xbd\x19\x55\x92\xba\x8a\x3e\x2e\xe9\x11\x0e\x0a\xb0\x46\xbe\x0c\x64\x2e\x4e\xe7\x37\x73\x59\x5e\x98\x3e\xbc\xbc\xb0\xba\xbe\x3b\xbf\xf3\xc3\xff\x3e\xbf\xda\x3f\xf9\x78\x7e\xf8\xf1\x3c\x4e\xdd\xec\xe0\x1b\x33\xab\x1a\xdf\x59\x43\x1d\xbb\x22\x0e\xb6\x79\x54\xab\x26\x7e\xfd\x83\x58\xbf\x66\xe2\x3e\x63\x31\x37\x01\x83\x5b\x8b\x28\x7e\xb5\x83\xba\x55\xaf\x9f\x83\xb4\x63\x6e\x15\xc2\xc5\x56\x16\x91\x07\x33\x6b\x69\xbb\x30\x9c\xf7\xc7\x9f\xcf\xce\xaf\x3e\x9f\x1d\x5e\xed\x9d\x9f\x9f\x1e\xbd\xfb\x7c\x7e\x18\xf7\x85\x0e\xfc\x74\x7a\xf2\x09\x46\xf0\x7f\xc5\xaf\xc4\x2f\x7b\x67\x57\x67\x47\xe8\xaf\xeb\xfd\x7b\x38\x2e\x9e\xc5\xdf\x53\xd0\xbb\x93\x93\x0f\x87\x7b\x1f\xaf\xfe\xba\xf7\xe1\xf3\x61\xfc\x13\x85\x7d\xfc\x7c\x7c\x78\x7a\xb4\x2f\xc3\xfa\xaf\x29\xf0\xd3\xc9\xd9\xd1\xf9\x11\xf6\x9f\x13\xfb\x3d\x7f\x02\x1d\x7b\xfa\xe1\x64\xef\xe0\xf0\xa0\x91\xe3\xeb\xef\x05\x7b\x3e\x82\x5d\x5c\x1d\x3d\xf6\xc9\x3c\xdf\xe7\x3a\xb2\x27\x93\xe4\x19\xbb\x50\x41\xf1\x19\x7c\xb8\xb7\x80\x7e\xba\x5e\x2e\x88\x75\xe5\x98\x94\x63\x3e\x59\xa7\x02\x8e\x58\x72\xc4\xf1\x72\x41\xfc\xd7\x71\xb6\x98\x94\x23\x8a\x1a\x00\x21\xad\xf7\x97\xf5\xa2\x9c\xe9\x0c\xd1\xa0\xe4\xaa\x15\xfa\x5e\xd6\x4c\xc9\x4d\xda\xdf\x99\x35\x35\x64\x79\xde\x7d\x1e\x6e\x22\xd4\xf1\x19\x6c\x87\xa3\xb4\x1a\x61\x85\x3c\x26\x57\xa2\x99\x06\x2d\xaf\x36\x77\xa4\x90\x73\x08\x33\xfe\x43\xf9\x55\xdd\x1c\xd1\xa6\xce\x7b\x79\x5d\xe7\xc0\x3f\x3a\x1f\x4e\x2f\x93\xa1\xf0\x18\x6d\x69\x32\x06\x59\x0f\xba\x3f\x9f\xe3\xe7\x14\xed\xf4\x2e\xd6\x67\xbe\x22\x71\xa0\x3f\x72\x2a\xf3\xb4\x3a\x1e\x83\x53\x8f\xf5\x58\x0a\x11\xb1\x2c\xc4\x1d\x0f\xfc\x62\xe9\xf9\x02\x7d\x1a\xc6\x5a\x75\x64\x9c\x64\xdc\x06\xf4\x08\x0c\x8c\xa0\xae\x0b\x7e\x5e\x85\x63\x01\xb4\xa5\x35\xfd\xb1\x8b\x65\x7a\x95\xb3\x27\xb9\x5a\x18\x98\x1a\xaa\x71\x96\x8f\xb2\xc3\xf1\x18\xa6\x69\x6d\x12\x37\x57\x8c\x4c\xfb\x8e\xad\x17\x48\x70\xe9\x26\x76\x66\xbe\x4c\xfd\x11\xa1\x29\xf2\xa1\x27\xb5\xb3\x8e\x64\x6a\x75\xa5\xd7\xfd\x95\x7f\x19\xca\xcf\x4f\x6e\xb3\x6a\x5a\xa6\xa3\x6c\xd4\x5d\xc9\xae\x95\x8a\xa8\x76\x9b\xde\xae\x86\xa3\xa7\xaf\x4b\xf1\x03\x5f\x38\x25\x6f\xf5\x29\x65\xbf\xe9\xeb\xc0\x6d\x19\xdc\x68\xb3\x0a\xee\x6c\xd3\xcf\x49\x9f\x0c\xbb\xd0\x7d\x13\xde\xde\x1c\x1d\x98\x49\x70\xf5\x71\xef\xf8\x30\x26\x4d\xc0\x17\x64\x9b\x9e\x8f\x02\xe1\x2e\xbc\xf8\x9e\x20\xdc\x7c\x6b\x43\x46\x39\x53\x5f\x25\xb7\xa6\xbd\x0c\x72\x67\x36\x06\x36\xfb\xd0\x0a\x53\xdf\x63\x90\xdb\x47\x32\xc4\x6e\xa4\x0c\xb2\x3b\x46\x06\xf9\xe6\x89\x8c\xf2\xf7\x17\x46\xae\xa1\x73\x31\xf0\x24\xad\xd8\x0e\x8c\x8d\x9d\x41\xf6\xf3\x7a\xa2\x29\xd9\x8b\x4c\xa1\xb6\x14\xc9\xda\xf4\x17\x19\xdd\x4d\x14\xe4\xa9\x4f\x79\xc4\xd4\x6a\xa0\xd8\xc5\x12\x34\x55\xdd\xb6\xe8\x4e\xf4\xdc\xb7\x88\x2a\x49\xd1\x83\x9f\xe2\xc2\x1f\x1e\x42\x7c\x4f\x2a\x74\xf2\x25\xc8\x17\x18\x86\x15\xe6\x42\xaa\xe1\xd8\x24\x12\x15\xda\x42\x14\xf0\x8f\x1f\x57\x72\x03\xc3\xfb\xdf\xb2\x79\xe5\xe7\x95\xe2\x3e\x86\xcf\xd5\xa1\x43\x20\x7d\xab\x3e\x3c\xe4\xad\x55\xb2\xb8\xdc\xda\xda\x54\x31\xce\x42\xc1\x18\xb6\x53\xcd\x22\x19\xef\x25\x22\x98\xae\xff\x56\x65\xd1\xb1\xa8\x30\x51\x46\xee\x33\x9d\xc3\x84\xd9\x66\xcd\x89\xe2\xf7\x65\xb9\x30\x33\x5c\x8d\x8c\x04\xc9\xa5\x43\x45\xf3\x06\xb1\x79\x83\x77\x74\xe0\xf3\xfa\x98\xf7\x5a\xeb\x98\xec\xbf\x4a\xd2\xeb\x6f\x64\xd1\x31\x11\x50\x35\xf1\x91\xad\x18\x4d\x55\x9a\x69\xa0\xf9\x6c\x19\xc7\xaa\x9e\x8e\x39\x54\x01\x2c\x7a\x6b\x37\x34\xd3\xcc\x37\x62\x4f\xec\xea\x9d\xdd\x22\x2e\x64\x13\x8d\x5d\x44\xde\x66\x39\xd0\x60\x47\x4e\x91\xdd\x20\x88\x17\xfa\x9b\xb8\x75\x1d\xe9\xed\x17\x69\xf7\xf7\x58\xcf\x64\xbe\x9e\x81\xb5\xc0\xe2\x0a\xee\x86\xc6\x66\xce\xeb\xb7\x8c\x4a\xf2\x7a\xc5\x77\x89\x2c\xd4\x40\x01\x29\x5d\xa0\xb0\xa8\xb8\x59\x3f\xea\x68\x9d\x3e\x6f\x6f\x3e\x50\xee\x02\x45\x2d\xa6\x13\x3c\xc3\x90\x5d\x8a\x20\xd8\x2e\x1c\x5b\xf0\xbc\xc5\xa3\x60\x25\x9b\xdb\x52\x86\x96\xe2\xc1\x36\x99\x11\xa1\x60\xa7\x40\x0f\x8e\xf8\x82\x22\x0f\xae\x96\x67\x1c\x6c\xcf\x54\xbb\x0b\x79\xdc\xb2\xa3\xe3\x46\x9d\x33\xae\x1f\xc9\xf1\x7c\xdd\xf0\xfc\xe9\xbb\x76\x90\x8a\x35\x83\x54\x44\x58\x08\x4b\x6a\x1f\xef\xf9\x66\xd3\xbc\x9d\x6f\xf5\x7b\xe5\xed\x77\x21\x67\x4d\x07\x15\x0f\x8d\x54\x9a\x14\xd8\x3b\x07\xa9\xba\xc4\x13\x3b\x0d\x11\x3c\x96\x8f\x0d\x91\x6f\x64\xd0\x39\x55\xcb\xe5\x84\x4d\xdf\xe2\xd7\x24\x98\x5a\x4f\xdd\xe0\x54\xd7\xf7\x5c\x3c\xbf\x7e\x06\xbc\xa0\xed\xa7\xda\xd2\x0e\x13\x16\x3a\x0b\x99\x9c\x59\x64\xb8\x53\x33\xc4\x02\xb5\x21\xd1\x04\xa2\x74\x33\x89\x34\xc2\x9d\x6c\x36\x5f\xdc\xa9\x1d\xd7\xc8\x76\x70\x9a\x50\x4a\xf4\xbe\xae\xf1\x91\x9d\x33\xe6\x10\xb1\x06\x7e\xbe\xf8\x9f\x8d\xbf\xbd\x7c\x7b\xb9\x1d\xbd\x14\xd3\x84\xf9\x2a\x96\x58\xbc\xa0\xfa\x06\x88\x9e\xdc\x21\xc2\x70\xa8\xfc\x32\xb4\xd4\x43\xcc\x21\x0a\x9d\xc0\x00\x87\x32\x07\xe6\x62\x6e\xe4\x13\x73\x60\x20\x96\x30\xda\x73\x74\x6c\x8f\x78\x2c\xf2\x09\x6f\x1a\x77\xb3\x38\xf8\xaf\x40\x14\x6a\xaf\x26\xb1\x0a\x3e\xe0\xc1\x06\x13\xca\x13\xc4\x05\x8a\x69\x76\xa8\x20\xda\xfc\x0b\x12\x10\xb5\xd7\x13\x2f\x9d\x91\xb8\xa5\xdc\x28\xfd\x08\xd3\xdf\x62\xfa\xdb\x66\xfa\x91\x4c\x3f\x4b\x6e\x2f\x46\x50\x14\xfc\x4b\x66\xda\x66\x70\x28\x82\xff\xec\x6f\x04\xdb\xd3\xed\x3f\x21\xe4\xdf\x68\xfb\x4f\xc1\xc6\x9f\xa2\x95\x6a\xec\x4d\x52\x42\x8e\x64\x6c\x8a\x66\xd3\x29\x6a\x8d\xef\x0c\xee\x7e\xbe\x51\xed\xde\xde\xbe\xe3\xec\xaf\x92\x9b\x8b\xbb\xcb\xc1\x15\x16\x6f\x1d\x59\xdd\xf7\x70\x8a\xf4\x68\x94\x6c\x5f\x39\xab\x13\xa5\xb8\x57\xad\x25\x00\x81\xcb\x70\x73\xec\x69\x8f\x18\x63\x23\xae\x04\x61\x84\x6b\x70\x8f\x65\x88\xd7\xf9\x63\x7d\x9d\xbf\x0c\xc7\xe6\x96\x5f\x83\x7a\x88\x31\x90\xb6\xc7\xe4\x82\x2e\x91\x73\x27\x82\x40\xf3\x10\xf8\x17\x4c\x16\xb3\x69\x40\x28\x45\x8b\xf4\x86\x28\x9f\x73\x22\x8e\xe4\x66\x0c\xdb\x1e\xf4\xdb\xc5\xce\xe5\x60\xe1\x4a\xbe\xa8\x60\x16\x7d\x15\x24\x95\x6f\xa1\x24\xaf\xd7\x5a\xf1\xae\xa2\xb8\xff\x9a\xc4\x3d\xee\x22\x82\x50\x12\x79\xbb\x6b\x08\x78\xc0\x8e\xbb\xfd\xa7\x61\x2f\x3a\x77\x4d\x79\x72\x51\x85\xf7\xa7\x59\x3d\x2f\x71\x3d\x59\xc2\x75\x75\x79\x04\xd1\x67\xf9\x6c\x3e\xcd\xfc\x71\xe7\xe9\xdc\x1f\x71\x88\x1e\x9e\xc8\x93\x93\x3f\x9e\x6f\x81\x3a\x0a\xa4\xab\x22\x7f\x9c\xa5\x6e\xef\x4f\xb0\x57\xa4\xd3\x3b\xf4\x9b\xee\x8f\x66\x34\x2b\x06\xb3\xa2\xbb\xac\x76\xb2\xcb\xb6\x31\xa3\x2b\xcb\x7f\x4c\x85\xd7\xea\xe8\xd6\x05\x65\xde\x79\x11\x59\x36\x2e\x15\x49\xb1\x5a\xdd\x2c\xa6\xb6\x98\x1d\xf5\x76\x0d\x89\x55\x63\xb9\x4c\xaa\xc6\xbd\xe1\x30\x49\x71\xc5\xbe\xcf\xab\x7a\x41\x5f\xa2\x27\xc2\x69\x72\x3f\xa3\x9c\x71\x80\x62\xd8\x24\xdc\xab\xc4\xb8\xc6\x4b\xc2\x63\x93\x42\x76\x9d\x7b\x41\xb8\xd4\x9a\xdf\x27\xcb\x85\xb0\xde\x80\x17\x85\xf3\x0c\x15\x40\x83\xbf\xb6\x00\x4e\xf1\x07\x0a\x40\x42\x7e\xc1\x06\x50\xf0\xef\x52\x8c\x9d\x8b\xb1\xe9\xa3\xaa\xe6\xd2\x0e\xcb\xcd\x96\x80\x3b\xab\x0c\xaf\xac\x46\xe7\x69\x75\x83\x9e\x8c\x2a\x12\x17\xcb\xa3\x5b\xe4\x98\x1e\x61\x1e\x9b\x4e\x1e\xcb\x05\xdf\xaa\xbb\xd9\xb6\xec\x95\x6a\x36\xb0\x66\x93\x17\x14\xbe\x46\x75\x92\x19\x16\x67\x9c\x64\xbd\xf2\x6b\x91\x55\x07\xf2\xfc\x38\xa8\x93\xf1\xee\x58\xf9\x2e\xfb\x6b\x9e\x7d\x7d\x78\x18\x4b\xa2\xc4\x00\x6b\x12\x4f\x9b\x8d\x96\xc4\x68\xd0\x6e\xde\x72\xb1\x0b\x74\x36\x13\xa3\x64\xe8\x6b\xe4\xa2\x54\x4d\x7c\x78\xa8\xa3\x18\x92\xd6\x90\x34\x43\x67\x5a\x49\x32\x6a\xb5\xe0\x36\x99\xec\xd2\xcc\x3a\x3a\x08\x27\x51\x1c\x04\x62\x96\x8c\x74\xc8\x88\x42\x60\x0f\xb2\x2e\x09\xa7\x3d\x33\x25\xc4\x2d\x72\x61\x37\x7c\x43\x12\x50\xf8\x14\xc3\xe1\x1b\xa0\xc9\x58\xa5\x64\x02\x8f\x4e\x25\x93\x91\x74\x35\xed\xc9\x94\xa6\xa9\x98\x59\x96\x5e\x77\x76\xde\x19\x46\x07\xe2\x4e\xe5\x3d\x12\x77\x8d\xbc\x27\xa8\x72\xa5\xaf\x2b\x0d\xe1\xb2\x2e\x2c\x6f\xc4\x1d\x54\x7b\x16\x89\x39\x6c\x09\xc9\x0d\xfc\xf4\x2f\x93\x3b\x31\x77\xc8\xff\xf8\x8f\x98\x25\x58\x2b\x3a\xee\xb3\x4b\x46\x1f\x05\x88\xfb\x3f\x7c\xd7\xbe\x54\x7c\x86\x2e\x30\x7c\x78\x9c\x23\xea\x1d\xd1\x20\x20\x84\x4a\x61\x80\x6f\xbb\x94\x8a\x80\x5c\x8c\x08\x4e\x77\xaf\x2c\x68\x59\xa1\x4d\xa9\x01\x98\x57\xa4\x9e\xe6\xad\x6d\x69\xd4\x08\x36\x36\x3a\x8d\x08\xcb\xb0\x85\x63\x48\x69\xee\x38\x2b\x96\x56\xd8\xfc\xce\xbc\x2c\x4d\x36\x07\xe5\x12\x5a\xe1\x56\xe5\xa0\x4a\x6f\x9c\x17\xbb\x42\xfc\xae\x08\x9b\x0e\xf9\x96\x2f\x9c\x00\x43\x9a\x54\x08\xae\x65\x27\xc0\x6d\xcf\x01\x0c\xad\x7e\x21\x78\x41\xfd\x46\x7a\x12\xfa\xcd\x98\x92\x09\xcb\xe0\xd9\x7a\x67\x93\x4c\x2b\xe0\xb3\xcc\xf8\x3f\x90\xba\xc3\x41\x5f\xc7\x19\x9b\x67\x27\xe4\xb8\xb4\xaa\xae\xd6\x7f\x23\xc0\x6e\x0c\x85\x7c\x36\xb5\x67\x93\x51\xf5\x76\x4a\xfa\x8e\xea\x8d\x7d\x10\x99\x57\x57\xa9\xc3\x84\x2f\xaf\x67\x56\x8f\x1a\x83\x5a\x1d\x52\x2e\x87\x13\xf6\x7f\xea\x86\xd9\x63\x45\x01\x4e\x6b\x28\xc4\xed\xf8\x5f\x27\x99\xcc\x63\x85\xdb\xe4\xbd\xb3\x05\xc6\xa5\x50\x6b\x0e\x2a\x49\x6a\x08\x75\x9c\xaf\xda\x47\x34\xb3\x3c\x60\x6d\x21\x20\xcb\x6b\x8f\x92\xaf\xb5\x9c\x9a\xc7\x9d\x3c\xb9\x67\xac\xdc\x2e\x17\xd5\x8b\xb6\xc7\x84\xb0\x1d\x46\xc8\xcf\x9b\xfd\x08\x1d\xf3\x20\x5f\xed\xe8\x89\x7a\x7d\x2b\xc8\x0f\xe0\xdc\x19\x2f\x6c\x15\x3b\xca\xdd\xd5\xb8\x0b\xb6\x09\x3a\xda\x9b\x75\x43\xb1\x8e\x93\x62\xa6\x52\xe7\x4a\x51\x88\x7f\x45\xf3\x76\x9e\xdb\xbc\x1d\xaa\x89\xfa\xa6\x22\x25\x5c\x64\x2a\x60\x8f\x94\x26\xc5\x56\x3e\x3e\x2c\x8a\x36\x5f\x0d\x23\xfc\xe3\x63\xba\xb0\x4d\x36\x8e\x99\x44\xa9\x7b\x75\xd7\xe4\xe5\x28\x52\xb9\x06\x2e\x95\xbb\x67\xb5\xab\x1c\x15\x8b\xd2\xb0\x71\xd2\x8a\x68\x4f\x47\x8f\x3a\xb5\x21\x56\x46\x13\xc1\x3e\xe6\x1a\xa8\xbe\x2c\xc9\x09\x1f\x0f\xdd\x82\xcb\x0d\x0b\xce\xba\xe4\x01\x81\xeb\x74\x5c\x8e\x96\x53\x94\x2e\xf0\xe8\x2e\xa2\x41\xb1\xb5\x55\x34\xbf\x41\xcb\x84\xa4\x15\x8a\xda\xc8\x8d\xa0\xac\x3e\x2a\x4e\xd0\x6c\x86\x8e\x59\x28\x4f\xa8\x3f\x21\xaa\x06\x0e\xd8\x22\x8c\x10\x27\xc3\xd6\x16\x55\x36\xeb\xa4\xc0\x34\xe7\xa6\x00\xbb\x66\x24\xde\xf2\x91\xd1\x47\xf2\x9e\x8e\xe8\x59\xe1\x52\x40\x7e\x24\x21\xc3\xd8\xa9\x98\x73\xec\x9f\xa3\x03\x09\xf2\x81\xee\x4f\xa2\x27\xea\x5c\x49\xdb\xad\x51\xa3\xe6\xc4\x55\xcf\x1f\xd1\x4e\x5f\xbf\xe3\xeb\x19\xcf\x17\x32\x6a\x25\x88\x1f\xc5\x47\xd5\x6f\x7c\x27\x5d\xc3\x47\x5d\x51\xa2\xc9\x2a\xf3\xc8\xe1\x27\x1d\x31\x02\x48\xaa\xc7\xb3\x0b\xcf\xe5\x3a\xdc\x2c\x1e\x1e\x3c\xd0\x28\x85\x42\x37\x5e\x92\x58\x23\xc4\x1f\xbc\xbc\x18\x54\x78\x8f\x51\x50\x3f\x7a\x73\x55\xd2\x3f\xfc\xc0\xf2\xe8\x5b\xa0\xd5\x9b\x94\x3c\x3e\xfe\x1d\x7c\x20\xd5\x7a\xed\xef\xf6\xa6\x53\xf5\x69\xed\xbf\x16\x42\x59\xc9\x32\x92\x9f\x62\x4e\xf4\xf5\x63\x2a\x70\x1a\xf5\x4b\xa0\xfd\xca\x9c\xc7\xc8\x87\xea\xb5\x54\x77\x49\x12\xd5\x0b\x16\xd8\x54\x5d\x74\x4f\x7b\x4e\x31\x3a\xf7\x01\xc2\x5c\xa0\x2d\x4d\x2a\xe6\x91\x11\x69\xc0\x96\xe2\xe8\x9f\xbb\x28\xe8\x64\x80\x54\x86\x43\x81\xaa\xc3\x4a\x29\xc9\x68\xa5\xb7\xcd\x23\x86\x03\x49\x01\x50\x59\x6e\x8a\x86\x52\x9b\x43\xf8\xf2\xea\x6a\xbe\x04\xf6\xd5\x4e\x8f\xe4\x02\x23\xac\xf1\x7b\x97\x16\x5f\x3c\xab\x60\xd9\xc9\xb8\x36\x88\x5c\xfc\x63\x5f\xf8\x48\x5c\xfc\xe3\x2b\xd1\x26\x70\xc0\xa5\x92\x92\x8a\x87\xbe\xc5\x7d\x16\x80\xb4\xc4\x16\x3f\x3e\xc3\x57\x1e\xfb\x7b\xd6\xaa\x4a\x0b\x9e\x13\xca\xed\x34\x4c\x08\x51\x58\x08\xb9\x0c\x70\x95\x86\xc5\xdb\x17\xb0\xa3\x6e\x0e\xd5\xf0\xa3\x79\xc7\x7d\x1a\x66\xee\xa8\x46\xc2\x4e\x90\x28\xfc\xd8\xac\x67\x4e\x96\x5a\x9a\x58\xd2\x2d\x5f\x94\x86\x79\x58\x21\x6c\x5c\x26\x4a\x1c\x7f\xc7\xd8\x81\x5b\x92\xc2\x60\x75\x2e\x78\x8f\xcd\x98\xe8\x4e\x4d\x90\x6d\x1a\xd5\xb6\x43\x11\x98\x74\x3d\x2d\x8c\x2e\xae\x28\xa1\x31\x76\xd8\x82\xd5\x04\x78\x36\x28\x15\x92\x69\xe3\x82\x74\x63\xd1\x22\x3e\xbb\x61\x19\xb6\x43\xe9\x6b\xdc\xab\x11\xb8\xdb\xb6\xc7\xb0\x3a\xa2\x83\x8c\xe1\xbd\x98\x58\x17\x0b\x27\xd7\x76\xf4\x81\x25\x30\xa0\x34\xd6\x48\xa1\x2d\x8f\x2d\x50\x60\xff\x7d\xed\x0d\x56\x5a\xeb\xc8\x7d\xf6\x5e\x8e\x3f\x5e\x56\x77\xd2\xef\xfb\x55\x27\x9d\xf6\x44\xd9\x95\xc4\xf8\x8e\xbd\xc7\xa6\x10\xd0\x53\x35\xd6\x8c\x91\xd7\x0c\x08\x19\x61\xd1\x2a\x04\x32\x51\xa1\x87\xb8\xce\x9d\xa9\xad\xf9\xb4\xd9\x7f\x8e\xd5\x62\xce\x56\x8b\x2d\x0d\x9a\x02\x21\x78\x71\x22\x26\x49\x8e\x17\xdf\xe1\x26\xbe\x45\x82\xc2\x72\x41\xfe\x4e\x56\xe4\x5f\x8d\xfd\xd7\xf9\x38\x10\xaf\x5a\xd6\xc8\xe9\x65\x96\x90\x34\xfb\x52\xc9\x21\xba\x67\x4a\xfb\x1b\xa9\xbb\xea\xb6\x3d\xeb\x5a\x3d\x6c\x34\xd9\x11\xd9\x6d\xe1\xb9\xae\x42\x1d\x99\x41\x7f\x5d\xf2\x5a\x55\x7a\x04\x0e\x92\x8f\xb8\x22\x83\x30\x7b\x64\x1d\xaf\x26\xae\x45\x9b\xa4\x83\xad\xd1\xc2\x3b\x68\xbd\x61\x2e\x2e\x07\x9a\xc0\x69\x7b\x36\xe9\xaa\xb3\x9b\xe8\x34\x3a\x2e\x6a\x5d\x14\x16\xa6\x0c\xf2\x9c\xf3\x48\x8f\x0c\x1a\x94\xc9\x43\x96\x74\x7e\x48\x97\x3c\xde\xcc\x3c\x5b\xc8\xf3\x1c\x97\x5a\xe6\x25\xb3\x9e\x39\xff\x02\xe7\xaa\x42\xd4\x49\xb4\x19\xc4\x07\x56\xbf\x2f\x56\x37\x3b\x3c\xb5\x36\xbf\xc6\xb0\x86\xa5\x9a\xf7\x5b\xb6\xc6\x71\xbf\xa5\x33\x6f\xcb\x5e\x4d\x19\x00\x5f\xa9\xe5\xa3\x79\x28\xb2\x70\xd4\xc1\x47\x07\xb4\x31\xb8\x58\x8e\x30\x7f\x0d\x94\xe3\xce\x20\xff\xb9\xd0\x4e\xfe\x36\x89\xab\x37\x07\xe7\x33\xa8\xc6\x3c\x1b\xa1\xc2\x20\xb0\x49\x19\xde\xc2\x23\x48\x66\x45\x06\xc4\x6c\xd9\xbb\xb5\x45\xc1\xe8\xce\xc8\x05\x86\x63\x05\x73\xe9\x5f\x45\x4a\xdc\x6e\x7b\xc4\xd6\xe3\x19\x85\x10\x04\x35\x47\x9a\xf1\x05\xbf\xde\x7a\xdc\xcf\x88\x56\x57\x0d\x2b\x3a\x32\x0c\xe5\x93\x48\xbb\x1b\xa4\x31\xa6\xd3\x13\x49\x0b\xad\xcd\x90\x21\x4f\x47\x16\x8f\x76\x64\x66\x81\x62\x56\xd0\x93\x95\xf6\x2b\xb5\xae\x27\x2b\x56\x25\x47\xc4\x4d\xea\xcf\xea\xd2\xc8\x97\xe1\x65\xa5\xae\xce\x33\xd9\xb3\x26\x76\x60\x53\x0a\xdb\xbe\x4f\xb5\x83\x20\xd9\x75\x1f\xb6\xda\xbe\xa6\xa7\x32\x07\xb8\xec\x79\xfd\x32\x0a\x5b\xd0\xac\x7a\x58\x77\xb9\x09\xac\x79\xd9\xae\xd9\xe3\xe3\x65\x0f\xfb\xd8\xac\x9c\xcd\x4d\x5f\x2e\x4f\x41\xef\xb2\xb9\x80\xdb\xe4\x9e\x8f\x9f\x54\x92\x7d\x1e\x75\xb6\x2a\x9e\xb4\x09\x82\xb2\xce\x5a\xe8\x52\x37\x88\xee\x00\x24\x23\xaf\x27\x31\x1c\x19\x6b\x5c\xec\xf8\x9c\xb3\x56\x60\xb5\xc0\x97\x52\xe8\xc3\x34\x3a\xd3\x56\xb4\x36\x9e\x8b\xc6\x21\x3b\xae\x9b\x21\xfa\xd8\x1d\x2f\x3b\xa3\x70\x72\xed\x2d\xce\x2b\x38\x45\x4c\x51\x53\xcf\x24\x88\xc7\x96\x8e\xd9\xad\x00\x22\xc3\x24\x8e\xcf\x27\xc0\xb0\x59\x54\xf6\x66\x9d\x18\xbb\x4d\x7b\x9f\xa7\x79\x6e\xc4\x68\x59\x63\xcf\x5f\xb3\x53\x6a\x04\x3c\xc2\x80\xf3\x70\xd9\x4c\xc3\xb2\xdd\xdb\x9e\x92\x6a\x23\x7a\x18\x8b\xb4\xd9\xd1\x0a\x9f\xd7\x4a\xd4\xab\xf1\x4d\xbb\x89\x37\x18\xdd\x09\x17\xee\x5c\x74\x12\x42\x00\x9d\xe2\x5c\x9a\x8e\xb7\x40\x4f\x6c\xdb\xd6\xd6\xd8\x12\x78\xb4\xc4\x17\x61\xd4\x83\xd4\x88\x59\xaa\x8d\xa8\x42\x93\x35\xde\x09\xa3\x74\x42\x2c\x9a\x86\xcc\x52\x11\x8b\xc4\x3c\x8d\x8a\xb4\x78\x2a\x39\x1a\x8f\x26\x14\x79\xc2\xdd\x3f\xc8\x9f\xd9\x89\xf9\xd3\x3a\xd1\xd9\x36\xfc\xbd\xd8\xac\x13\xd9\x8f\x35\xfb\x83\x29\x88\x6b\x6b\x1d\xdd\xa3\xa1\x6d\x19\xb5\xcc\xa9\xf1\x32\xf0\xa9\x43\x60\x2e\x86\x10\xb2\x43\xa4\x62\xe1\x58\x9e\x4f\x55\x31\x35\x2b\xd5\xcc\x3b\xe8\xcf\xb8\xc3\x42\x75\xd2\x21\x32\x1c\xad\x11\x19\xde\x26\xf3\x5e\x4b\xbe\x0d\xc4\x69\xdc\xb3\x44\x00\x48\x9a\xd6\x59\xe3\x01\x41\x31\xd1\x2e\x61\xa2\xcb\xd4\xf5\x57\x63\xf1\xf0\xc9\xb4\xc3\x6f\xba\xf7\x3c\x11\x02\x52\x9c\xa7\x79\xa7\xdd\xf4\xc2\xf5\xf3\x4d\xe9\xc3\xc3\xa6\x44\x16\x56\x4a\xba\xed\x10\x57\x6d\x97\xd1\x92\x95\x3a\x09\x50\x78\x7e\xfe\xb5\xc4\x39\x57\xc7\x3e\xbc\x6b\x8e\x93\x09\x1d\xa9\x76\x1d\x57\x08\x21\xbc\xd9\xe1\x4a\x19\x61\x10\x5b\x4e\x9e\x23\x99\x11\xde\xff\x62\x5f\x53\x16\x2a\x5d\x0d\x75\xcd\x80\xc2\xc1\x46\xc0\xa5\xc6\x9b\x95\xc7\x34\xf0\xc7\xe7\xe9\x8f\x31\x86\x45\x55\x96\x0b\xed\xdb\xae\xc6\x9d\x0c\x6f\x73\x12\x05\x02\x8d\x2f\xda\x1f\xdd\x58\x82\x60\x50\x8a\x7f\x06\xd4\xe4\xc6\xb1\x72\x82\x49\x90\xd5\x35\x5e\x5d\x36\x11\x4e\x64\x3a\x8f\x23\x3a\xed\x90\xd3\xb4\x62\xd7\x3c\xb2\x3d\x7b\x6c\x02\x2e\xd2\x30\xba\x64\x55\x70\x04\xf4\xb5\xf2\xc3\x63\x72\xab\x71\x1a\x5d\xbd\x15\x43\xb3\x8f\xfa\x36\x69\x74\x99\x40\x2a\x2b\xdd\x10\xe6\xcd\xfe\x2b\x8d\xf7\x27\x64\x25\x17\xc8\x46\xbe\x5d\xb0\x6c\x15\x0f\xdb\x78\x7c\x5b\x00\xc7\x28\x91\xc5\xaa\x17\xec\xf6\x24\x43\xef\x61\x6f\x93\x0c\x13\x56\x2f\x32\x4e\x5a\xc2\x03\xe9\xc6\xb3\xba\x41\x92\xbd\xed\xef\xf6\x5f\x64\xf2\x2a\x67\xd0\x59\x75\xa8\x02\xfb\xbb\x41\x1a\xe6\x19\xd1\x7f\x31\x38\x49\xc7\x18\x03\x5f\x41\xab\xfc\x49\xda\x4c\x62\x9d\x06\x79\x87\x3e\x23\xea\xee\x1a\x8a\xdf\xb6\xef\x11\xb5\x3f\x81\xb2\xe8\x11\x4b\x27\xbe\x65\x97\x23\x86\xad\x78\xdb\xc8\x87\x7c\xc8\xb8\xd1\x8e\xa5\x8d\x98\xb7\xe2\xfd\x26\x39\xb0\x93\x34\x13\x76\x99\xde\x90\xf6\xb4\xa5\x0d\x77\xcf\x0c\xb2\x26\x75\xa4\xe0\x85\x4f\xb4\x8d\x0c\xaa\x04\x4e\x2e\x13\x3c\x99\xbf\x07\x12\x08\x4c\x94\xfb\x86\x4a\x74\x8b\x79\xfc\xf2\xe5\xd7\xaf\x5f\x7b\x5f\xbf\xeb\x95\xd5\xcd\xcb\xf3\xd3\x97\x67\x7f\xfd\x73\xbf\xff\x72\xcc\x69\xfe\xaf\x77\x69\x9d\x0f\xcf\xe8\x16\x08\x5e\x03\x11\xf4\x7b\xfd\x40\x59\xa3\xde\xb7\x4d\x41\x18\x7e\xdf\xc6\xdc\xcf\xea\x45\xef\x1a\xe8\x5b\xf8\xf2\x7f\x42\xd4\x07\x7d\x40\xc6\x33\x7a\x71\x91\xbe\xf8\xc7\xd5\x25\xfe\xff\xdb\xe8\xaa\xf7\xb7\x17\x97\xff\xf5\x9f\x2f\x23\x61\xcc\xfa\x62\xdc\xec\xb2\xb9\x64\xe6\xf9\x19\x81\x61\xf5\x2d\x76\x4a\x33\xed\x2f\xd9\x9d\x7a\x25\xa6\x98\x9f\xa7\xd3\xf2\xeb\x7b\x78\x3a\x23\x82\x1a\xa7\x0f\x4b\x0e\x3b\xaf\xd2\xa2\x26\x95\x9b\xe1\x5d\x9c\x42\x98\xca\xab\xbe\x2b\x86\xb8\x81\x2e\x17\x25\x6a\x34\xa0\xdc\x42\xc6\x40\xc8\xa7\x69\x7a\x07\x91\xc3\x6c\x3a\xfd\x04\xcb\x06\xfd\x8f\xb3\xb6\x05\x04\x9c\x21\x48\xa1\x0e\x80\xfa\x9d\x65\x68\xa4\x4c\x90\x19\xc0\xbf\xd6\x50\x32\xf9\x37\x3e\x3a\xc0\x50\x7c\xe2\x2b\xa7\xdd\x14\xce\x06\xc3\x72\x5a\x43\xe5\xe6\xf8\x00\x19\xc9\xda\x0f\xa5\xa9\xb3\xfd\x72\x38\x62\x47\xc4\x56\xa0\x54\xad\x48\xe9\xad\xc2\x9c\xa8\xb0\xb2\xac\x46\x52\xed\x60\x58\x95\x75\x7d\x52\xe5\x4a\x25\x4e\x68\x90\x73\x41\x26\xaa\x39\x54\x24\x15\xb0\xe1\xd1\x69\x64\x94\x4b\x55\x02\x60\xc4\x52\x62\xbe\xb1\xdb\x60\x5b\x2a\xd0\x2a\x01\x4e\x1e\xa3\x2a\xbd\xb9\x31\x95\x80\x3e\xc4\x23\x13\xbf\x00\x11\x9b\x41\x5e\xf8\xc3\xfe\x3e\xe5\xcb\xa1\x4c\xc4\x6f\xd2\xf2\x89\x5f\x3e\x96\x7f\x4d\xa7\x39\xa9\x8c\x2c\x29\x80\xa5\x03\x18\x8b\x6e\xa1\xde\x31\x2c\x62\x2a\x26\x59\x3a\xc2\xbd\x96\xca\x99\x30\x2c\x1f\x84\xe6\xa3\x91\x1c\xd9\x09\x04\xc9\xd8\x2a\x1b\x9b\xa7\x0f\xa9\x1a\x17\x54\x16\x7d\xaf\x34\x39\x70\xd2\x1f\xfe\xbe\xcc\x6f\xe5\x31\x71\xa8\x66\x4d\x0e\xc3\x25\xa6\xe9\xb5\x52\x65\x98\xea\xef\x51\x25\x00\xca\x9c\x96\xe5\x9c\x3a\x19\x66\x12\x47\xcc\xd2\x22\x1f\x67\x14\x39\x83\xda\x03\x43\xc4\xf5\x93\x91\x18\xc2\xb0\x85\x32\xe0\x9b\x7e\x60\x0f\xb0\xf8\x5d\x36\xca\x53\xf5\xcb\xc8\x9e\x9c\x86\xfb\x8a\x9f\xd5\x00\xce\xd0\xca\x18\x66\x27\xd5\x62\x06\xeb\x8d\x67\x58\x81\x53\x8a\xf5\xe8\xec\x4e\x85\xa5\x54\xd0\xcf\x22\x9f\x2d\x67\x9c\x00\xd8\x3d\x60\xfe\x64\x76\xa4\x04\x3b\x29\xa7\x23\xa5\x45\x32\x2f\x6b\xad\x52\x33\xaf\xb2\xa9\xd6\x52\x21\xb4\x17\xab\x76\xc0\x53\x8d\x10\x5b\x8d\x8a\xaf\x54\x8f\x55\x19\xf4\x2b\xaa\x1f\x41\x18\xec\x13\xd0\x2a\x54\x84\xa7\x19\x0e\x0f\x66\x86\xd7\xc0\x93\x5f\x97\xb2\x33\xea\x61\xa9\x66\x11\x3d\xe2\xd7\x35\xa9\xa7\xe8\x75\x55\x67\xe9\x0c\xd1\x16\x69\xb8\x6b\xd2\x55\x91\x2d\xaf\x27\xa9\xfe\x18\xd1\x1b\xb1\x28\x7c\x80\xa4\xa2\xc6\xf2\xe0\x75\x0e\xcb\x74\x1f\xd7\xa3\x4c\x57\x0d\xf5\xc3\x41\x39\x84\x31\x87\x07\x5e\xb5\xb4\xc7\x03\xab\x0c\x9d\x20\xdb\x49\x90\x7c\x52\x47\x25\xbd\x66\x08\x07\xf9\x46\x93\x95\x9f\x11\x0b\x52\x3e\xea\x15\x81\xc2\xc3\x54\xe6\xc2\x5c\x4a\xfd\x30\x44\x60\x54\x1a\xf5\xaf\xb3\x72\x84\xfd\x43\x04\x27\x9d\xc3\xe2\x46\x0c\x3c\x43\x72\xf6\xcb\x0a\x19\x78\x39\x31\x17\xd9\x0c\x09\x23\xa4\xc7\xc7\x33\xea\x30\xec\x0a\x7c\x93\xcb\x0b\x1f\x89\xc6\xe0\xc3\x29\x2c\x03\x02\x4a\x60\xab\x11\xae\x4f\xc1\x1d\x47\x0b\x38\x5d\x89\x96\xb5\xb4\x22\xb8\x8a\xc8\x06\xfc\xfa\x62\xc8\xef\x81\x45\xbd\x02\x7a\x0c\xf4\xba\x0a\x60\xf9\x06\xd6\xc2\xa2\x8d\xe5\x05\x4e\x86\xdb\x80\x4a\x72\xac\xaf\xa1\x20\xb7\xd5\x01\xbe\x0f\xf5\x7b\xe0\x92\x61\x8e\x95\x6f\x81\xd3\x3b\x32\x8a\x5e\x38\x86\x75\xb4\x28\x9c\x1c\x97\x04\x86\x80\x53\x20\xcc\xf8\xbb\x40\x93\xae\x80\x9c\x85\x91\x23\x64\x4d\x30\x02\x7c\xc2\xa5\x1f\xd8\x93\x9e\xe1\x8e\x10\xba\x75\x1e\xd8\x33\x2a\xa0\x67\xa2\xf6\x81\x9a\x50\x01\xfc\xc2\x96\x1c\xa8\x79\x85\xef\xd8\x81\x8e\x0c\x7c\xd4\x69\x52\xd2\xa5\x76\x8e\xcc\xd4\x73\x40\x87\xa3\xfb\xa1\xf2\x9a\x2b\xbd\xbf\xc8\x4d\xe9\x43\x5e\x7c\x51\x0e\x86\x54\x14\xcd\x50\x8c\x88\x9a\x52\x71\xbc\xa4\x6a\x66\x44\xa9\x81\x57\x75\x02\x95\xf2\x58\x53\x8e\xe2\xcd\x41\x56\xe5\x09\x79\xa4\xfa\x08\xd3\xa8\x69\x0f\xa9\x0d\xd0\x5e\xe9\x36\x7b\x21\x15\x43\x39\x41\xd4\x14\x43\x98\x0c\xac\x5e\xe8\xca\x42\x26\x61\x36\x67\x69\xa9\x6c\xe3\x58\x29\x34\x94\x61\x5b\x00\x39\x4d\xee\x61\x39\x2d\x18\xff\x57\xa1\x66\xe1\x73\xae\xa0\x82\xe5\xb6\x05\x4f\x34\xa1\xe8\x21\x53\xa8\xc7\xac\x6c\x87\xe8\xb5\xf3\xe4\xfe\x38\xff\x06\x54\xff\x7e\xae\x4a\x8c\xef\x9b\xbe\xd1\x6d\xc5\xad\xcd\x05\xe9\x80\x4c\x2f\x18\x8d\xeb\x12\xd5\x77\x54\x67\xe2\xb3\xa2\xd7\xf8\xac\xf6\x77\x76\xea\x80\xae\x94\xa5\x1b\x65\xf4\xa9\x0e\xe5\xdd\xe6\xa3\x6c\xb4\x91\x6e\xfc\x46\x05\xfe\x86\x41\xf3\x8d\x45\x09\x21\xb8\x4b\x6f\x8c\xf3\x6c\xca\x3e\x95\xcb\xe5\x62\x23\x2d\x36\x7e\x53\x05\xfd\xb6\x31\x21\x61\x4b\xd5\xdb\x38\x87\xfe\x86\x34\xd3\xe9\x46\x45\x16\x3e\xf0\x31\x56\xe1\x45\x09\x75\xe0\x1c\x7a\x1b\x47\x63\x72\xd9\xce\xf9\xd5\x90\x1b\xfc\x5c\x67\x1b\xb0\xad\x61\xf5\x36\x70\x5e\xff\x36\xb2\x4c\xc1\x7e\xeb\x6d\x9c\xc0\x07\xd5\xd7\xbc\xce\xc4\x06\x74\xda\x46\x96\xe3\xbb\x5d\x81\x12\xde\x54\x5b\x7f\xeb\xa1\xbf\x63\xc5\x89\xad\xed\xb7\x7f\x41\x67\xc9\x72\xfe\x2d\xba\x6b\x5f\xd6\xe5\x0f\x75\x98\x56\x02\x5d\xf6\xb0\xcf\x56\x74\x9a\xfe\x6b\x63\xee\x59\x0a\x83\x8d\x65\xb9\x1b\xe6\x84\x1f\xda\x5a\xae\xbc\x2e\x63\x27\x82\xf2\xde\x6f\x8d\x50\x2b\x77\x6b\xcd\x92\xd6\x82\xc9\xdf\x5e\xcd\x8d\x12\x64\x14\x95\x71\xa2\x1a\xf5\x8c\x26\xa4\xad\xac\xac\xf2\x6b\x13\xa9\x3a\xcc\x67\x43\xd4\xa0\x1a\x71\xff\xbb\x57\x7e\xf1\xfb\x33\xfc\xc6\x2f\x8c\x92\x65\xe8\x18\xfe\x51\x61\xd2\xf6\x90\x84\x4d\x87\x40\x4f\x16\x36\xbc\xd3\xbf\x40\x91\x71\x51\xa5\xf3\x77\x2c\x9d\x6f\xaa\x01\x90\xa3\x1f\x96\xb2\xe0\xc5\xc9\x12\x0e\x29\x23\x63\x8a\xd5\x72\x37\x36\xa8\xcd\x85\x61\xde\x6b\xe6\xab\xf0\xca\x58\x7e\x31\x05\xfe\x60\xea\x0a\xdf\x10\xd2\xac\x2b\x0e\xaf\x17\x84\x76\x8a\xf6\x2b\x2c\xac\xcf\xc5\xcc\xeb\x17\xcd\xf7\x35\xc9\xa3\xd7\x65\xed\x81\x04\xea\xec\xfb\xf8\xa7\xef\xff\x55\x1a\x56\x8f\xe1\x15\x3f\xc1\x5e\xa9\xa9\xef\x5c\xb6\x8c\x8d\x52\xc7\x06\x87\x4f\x7a\x4f\x33\xc3\x29\xdd\x5b\x6e\xed\x87\x51\xee\xaa\x83\x74\x6b\x6b\x33\x85\xd5\x32\x44\x2d\x7f\xd4\xb8\x53\xcf\x49\x1e\xb9\x30\x4b\xe9\x3a\xf1\xb3\x57\x09\xf8\xa7\xe7\x00\xe2\x4a\xdb\x69\xc9\x7a\x44\x8b\x09\x0c\xdb\x06\x92\x76\x6c\xb3\x24\xef\x8e\xf4\x6b\x83\x5b\xb0\x31\x4c\x8b\xa2\x5c\x20\xd5\xc5\x6f\x91\x76\x1a\x79\x71\x64\x01\x13\x6b\xe7\x95\xa2\x6a\x3b\x21\x74\x15\x25\x60\x60\xfa\x83\xfc\x67\xc8\x9f\x44\x38\x5a\x97\x31\x57\x7a\x8c\x65\xa2\xe3\x24\x36\x37\x96\xbd\x99\x94\xaa\x7f\x65\x61\xa5\xa9\x40\x8d\x3a\x19\x69\x54\xb1\x92\x11\x1c\x6b\xc8\x0e\x1d\xfd\x8d\xa3\x8f\xda\xc8\x72\xc8\xee\x0a\xfd\xb0\x1f\x9f\x86\x6f\xd7\x22\x0c\xb9\xa3\xd5\x2c\xaf\x9b\x61\x09\xb1\x06\x90\xf2\x11\x8c\xd2\x43\x65\x0a\x2a\x95\x1e\x1a\x91\xf3\x72\x6e\x3c\x65\x49\x2d\x29\xb4\xcf\xb4\x3c\x64\xc1\x38\x91\x1a\x32\xcc\x5d\x9f\x72\xaa\x2a\xb5\xe8\x2e\x15\x05\xb8\xdd\xa5\x16\x5c\x6a\x45\xf7\x42\xa2\xb2\xcb\xe5\x82\x10\x49\xa6\xc3\xa4\x40\x96\x5d\x75\x97\x9d\x27\xd5\x9a\xb2\xe5\x90\xe5\x82\xb3\x15\xb9\x5d\xba\xba\x78\x45\x10\x9b\xe6\x22\xd4\x30\x91\xba\x0e\x65\x77\x1d\xd0\x15\x7b\x77\x1d\x4a\x35\x6d\x4c\xd6\x22\xb5\xeb\x51\x5a\x85\x22\x8c\x56\xc7\xc8\x43\x75\x6d\xe7\xd0\xa4\xd9\x61\x90\xb3\xe9\x5a\x50\xbf\x85\x28\x7f\xf6\xd4\xf7\xe7\x0c\xea\x56\x4e\xd1\x31\x03\xba\x2d\x74\x2b\xcd\x48\xe5\xa8\xf0\xd7\xdf\x41\x69\xac\x98\xfb\x27\x84\x19\x58\xfb\x7b\x34\xf8\x2e\x8c\x15\x1a\xc2\xa9\x4c\x21\x40\x15\x87\xd0\x2f\xfa\x05\x91\xf4\x0b\xa5\x02\x9f\x2c\x61\x32\xa2\xee\xbb\x2d\x41\x8f\xe7\xc0\x37\x65\x7b\x72\xa5\x52\x96\xe8\x15\x62\xf1\xb5\x6c\x84\x95\x02\xc8\x4d\xd6\x4c\x99\x8a\x71\x7e\xdb\x0c\xac\x3d\xba\xbd\xad\x4d\xe1\xa7\xc7\x74\xa6\xfc\xd6\x0f\x9f\xb5\x53\x72\xc3\x39\x90\x35\x34\xf0\x9f\x0d\x34\x48\xed\xec\xb6\x61\xbe\xaa\x6e\x80\x6a\x27\x2d\x09\x26\x0d\x40\x00\x87\xb2\xf6\xcf\x09\x5a\x43\x9a\x83\x13\x45\x19\xf4\xdc\xa9\xc4\x81\xb1\x83\xa5\x2c\x8b\x8c\xdd\x4c\x24\x30\x10\xe8\xb1\x62\x9e\x38\x41\x7c\x07\x61\xaa\x3a\xb6\xa3\x99\x2d\x3e\x52\x42\x76\x73\x4d\x4b\xd1\xee\x55\xb1\xa5\x5c\xe2\x98\xe9\xde\xda\xe7\xc0\xac\x1a\x1b\x4f\x70\xad\xa3\xe1\x8d\x15\x7e\x9a\xa1\x17\xe4\x7c\x4a\x4d\xbf\xb3\x22\xce\xb2\xea\x36\xab\x18\x00\x81\x81\x6f\xae\xfc\x77\x69\x12\xf3\x18\xb6\x99\x91\xe4\x9d\x0c\xdc\x31\x1e\x10\x68\xdc\x70\xff\x91\xb7\x08\x21\x33\x55\xdf\x92\xa1\x7b\xf7\x29\xbe\xea\x90\xf7\x29\xae\xba\x3b\xb1\x8f\x21\x53\xe8\x32\x95\x04\xfd\xb5\xcd\x60\x96\xd3\xf5\x00\x55\x33\x10\x01\x9f\x49\x02\x31\xea\xf1\x13\x42\x1d\xdf\xab\xd9\x12\xdf\xcf\x52\xc4\xf2\x84\xff\x42\x72\x33\xf0\x26\x9f\x80\x07\x63\x73\x10\xfa\x15\x58\xdb\xf8\x70\x25\xf4\x38\xc1\x72\xc0\x6b\xd8\xa9\xd0\xbd\x17\xcf\x44\x5e\xe4\x8b\x9c\x24\x41\xb6\x72\x8b\xc3\xb8\xf7\x5c\xcd\x17\x34\x1a\xe1\x86\xd1\xa4\x8c\xd3\x9e\xf5\x26\x9c\x4e\x88\xbf\x09\xbb\xc1\xf1\xbe\x70\x7a\x24\xfe\xaa\xa0\x83\xe8\xf8\xed\x3b\x2d\x20\x63\x29\xed\x62\xf6\xd0\xb7\x4f\x41\x7e\x79\x54\x83\x46\xbd\x35\xb1\xeb\xbe\x7c\x77\x77\x74\xb0\xfe\x6b\x4c\x21\xac\x59\x10\x5f\x0b\x1e\x8f\xf8\x54\x3e\x9c\x4b\xff\xc6\xf1\x5d\xcf\x0d\xb0\xe2\x53\x34\x48\x65\xa0\x05\x3b\x95\x09\x16\x4b\x66\x95\x75\xb9\x7b\xa4\xdc\x07\x75\xf3\x47\x88\xbc\xa6\x75\xaa\x7a\x74\xd8\x73\x03\x04\x9e\x7d\x25\x61\x88\xeb\x9e\xf5\x26\xae\xae\xea\x39\x1e\x3e\xe3\xab\xd5\xc0\x77\xf5\x7e\x75\x75\x7a\xb8\xb7\x7f\x7e\x75\x70\xf8\xd7\xf3\x93\x93\x0f\x67\x57\x7f\xfe\x70\xf2\x6e\xef\xc3\xd5\x2f\x27\x27\x7f\xb9\xba\xf2\xfa\x0b\x5e\xff\x89\x5c\x21\x5b\x5b\x4f\x4a\x16\xde\xdb\x94\x2b\x5e\x8a\x06\xa1\x88\x27\x82\xd5\xcb\x46\xc2\xac\xf2\xf8\x46\x38\xa4\x28\x9e\xaf\xa2\xc1\x99\xf2\x58\x9c\x04\x3b\xbd\xfe\x77\xbd\xef\x02\xeb\xbe\xf5\xac\x65\xb6\xe1\xd8\x66\xac\x83\xa1\xf0\xde\xd1\xba\xc4\x3c\xfe\xe9\xb5\x70\x49\x76\xcc\x7e\x52\x1a\xc4\x3d\xfe\xe9\x27\xd1\x24\xe3\x31\x23\x20\xb7\x89\x78\xfc\xc6\x18\x3d\x23\x39\x8e\xdf\x7c\x2f\x3a\x69\x71\xdc\xdf\x31\x38\xa9\x2d\x52\x0c\xb1\xa6\x60\x83\xbd\xdc\xef\x37\x03\xcd\x66\x00\xb1\xa6\x5e\x4d\xe2\x1d\xf7\x5f\xed\x74\x18\x64\x1b\xd2\x0d\x21\x6f\x44\x9b\x72\xab\xe3\x79\x93\x70\x43\xb8\x69\x41\x93\x6e\x43\x24\x35\xc0\xa6\xcf\x70\x86\xa3\xfa\x1b\xf2\x1c\xf7\xdf\xd0\x39\xe5\x31\x35\x3b\x6b\xbb\x76\x09\x7e\x4e\x58\xe4\x6a\xe9\x7b\x60\xa4\x25\x12\xb9\xcf\x85\x77\xa3\x66\x58\x8f\xe7\x40\xcf\xe9\x32\x1e\x39\xcb\x48\xa3\x06\x71\x1b\x11\xf6\xd2\xed\x65\x32\xd9\xde\x16\xf3\x0b\x7c\x24\xcb\x34\xf5\xec\xa0\x15\x35\x4f\xaa\x65\x8b\x59\x61\xc5\xaa\x74\x9d\x09\xa7\xcd\x84\xd8\xc7\x6f\x22\xe3\x86\x1d\x51\x5a\x37\xc7\x19\x36\xd3\x92\xe2\x36\xf7\xdc\x69\xa7\x07\x80\x39\xda\x98\x8c\xd1\x3f\x22\xba\x94\x19\x25\xda\xbc\x3e\xb8\x86\xff\x81\x65\x60\xaf\x30\xee\x8d\x91\x7d\x40\xc7\xdd\xc0\x63\x67\x1f\x58\x9e\x25\x61\x66\x35\x93\xb0\xa9\xb4\x9d\x88\xae\xaa\x9a\xc9\xa4\x05\xbe\x9d\x8e\x11\xb4\x83\xa6\x41\x7e\x20\xaf\x90\x61\x61\x2d\x03\x6d\x99\x0f\xa1\xf3\xbb\x40\xd9\xe6\x07\x40\x76\x82\xa6\x71\x7e\x30\xba\x9e\x9a\x56\x90\x89\x7e\x80\x17\xc3\xfa\x95\x5a\x83\x21\xaa\x19\xc6\x52\x5f\x06\x13\x8e\x83\x6d\xb0\xcf\xe1\xdf\xf2\x85\x0e\x66\xb3\x7d\x0a\x97\x98\x12\xb6\xf5\x3e\x85\x97\xb7\x56\x36\xb2\x7f\x30\xdc\x74\x0c\x99\xf2\x43\x58\x39\x0f\x8c\xf9\x7e\x20\xaf\x85\xb4\x05\xbf\x74\x15\x60\x1b\xf1\x07\x5f\xb2\x3b\xbc\xf7\x56\x81\x6c\xc9\x8f\xa1\x73\x7c\x52\xc1\x9f\xe7\x14\xb6\xe4\xec\x8d\x11\x3f\xe3\x55\xe8\x0c\x8c\x2d\x3f\x47\xa0\xdc\xce\x44\xa0\x49\x3f\x87\x97\xb2\x16\xc6\xb0\x5f\x86\xab\x86\x2a\xfb\x7e\x0e\x96\xc5\xb2\x91\x7f\x30\xc7\x9f\xc0\xb2\xec\x0f\xf8\x0a\x35\xf0\x59\xf7\x07\xb5\x0a\xb0\x66\xa8\xb1\xed\x0f\x16\xea\x31\x68\x9a\xf8\x07\x0b\x7c\x19\xd2\x8b\x89\xa4\x21\xa7\x18\x35\xe6\xc6\xe2\x9f\xc3\x75\x9b\x2d\xc3\x7f\x8e\x31\xc3\xc5\x00\x00\xc1\x57\xfc\x09\x56\xc0\x6e\x07\x57\x84\xc8\xaa\x25\x6f\x47\x07\xc1\x36\xb3\x33\xe1\x71\xba\x98\xf4\x2a\xa0\xf8\xe5\x2c\x8c\x22\xa9\xee\xf4\x0a\x19\xf2\x61\x88\x20\xaf\xe2\xde\x50\x02\x6d\xca\x6a\x69\x85\xe7\xc6\x60\xd9\x93\xd0\xb1\xf3\x44\x84\x3e\xde\x5b\xce\xa5\x9c\x2c\x9c\xf5\x26\x4e\x00\x94\xdb\x6b\x67\x43\x0a\xe6\x68\xfc\x53\xb0\x36\x85\x9d\xab\x2f\xfd\xd6\x96\x2f\xb4\x67\x72\xa0\xc3\x2e\x2a\xa7\x37\xf2\xd3\x77\x19\xe1\xa6\x2f\x87\x87\x07\x6f\x70\x4f\xe7\x14\xa2\x01\x2b\xa3\x1e\xc0\x41\xb6\x03\x4f\x3f\xc9\x48\x01\xbb\x40\x52\x9b\x3e\x66\xc3\x47\xaa\x55\x4d\x0c\xa3\x1d\x20\x9d\x5a\xbc\x35\x7f\x3b\x1c\x0c\x95\x88\x6b\x9c\x20\xf0\xef\xa0\x6c\xda\x10\x8d\xa3\xad\xad\xf2\x62\x8c\xb6\xcd\x63\x85\x83\x43\xb3\x64\x77\x1a\xca\x79\x12\xed\x7a\xdb\xd6\x12\x26\x9b\x6f\x85\xfc\x12\xcd\x18\x20\x1b\x5a\x4b\x7f\x3c\x2f\xeb\x73\xcc\xf0\xf9\x19\x20\x02\x39\xe6\x71\x26\x97\x2b\x64\xa2\xdb\xca\x61\xd8\x58\xb5\x98\x37\x77\xd6\x54\x52\xfa\x82\xb1\x0b\xe1\x1c\x84\xfe\xfe\x79\x55\x6c\x7e\xed\xfd\xf4\xd7\xa3\x8f\x07\x27\xbf\x5e\xfd\xb2\xf7\xf1\xe0\xc3\xa1\x55\x79\x22\xb7\x0f\x0f\xfa\x1d\xf7\xc8\xdd\x10\xda\x22\x09\x30\x36\x25\x7c\x4e\x5b\xd8\x4d\x8d\xfa\xbc\xf0\x2f\xba\xae\x8f\xc9\x09\x8e\xdc\xa1\xd1\x17\x93\xaa\x07\x32\x07\x5b\x5b\xdd\xf5\x68\x77\x8a\x5d\x0d\xf8\x7a\x6d\x45\xda\x5f\x73\x3d\xe8\x63\xa2\xf7\x68\x2a\x5c\x5e\xe8\x28\x84\x78\x57\xef\x54\x10\x06\x44\x70\xf4\xf2\xac\x8c\xa7\x95\x3a\x16\x23\x58\x41\x58\x4b\x5c\x49\x64\xd7\xb9\x12\x6b\xef\x70\x2c\x34\x90\xa7\x15\xa1\xa4\x92\xad\xae\x7f\x76\xb6\xee\xc0\xa9\x7c\xb3\x02\xc5\x11\x3c\x19\xe9\x1e\xf2\xb8\x2c\x72\x38\x07\xe0\x41\xd7\x55\xf0\xdd\x1c\x2b\x63\xfb\x25\x90\xa8\x31\x6c\xd6\x13\xeb\xb3\x7a\xe0\x2d\x78\xc6\xb9\x59\x09\x51\x70\x0f\x1c\x1e\x7a\x09\xec\x34\x1f\x2e\x9f\x0f\xff\x50\x3e\x09\xfe\xa1\xec\x59\x6f\x0e\x84\x43\xe9\x58\x03\x34\x70\x1a\xca\x9e\x1b\xe0\xc3\x63\x50\x69\xec\x40\x07\xe7\x74\xf6\x47\x3d\xf6\x78\xc1\x06\xba\x0f\xa7\x6d\x0e\x1d\x8e\x74\x74\xc2\x6a\x32\xe8\x71\xff\x87\x9f\x3a\x1d\xf7\xe0\x39\xe6\x31\x55\x78\xeb\x3c\xd5\x16\xc7\xc9\x23\xc8\x78\x8a\x4a\x71\x45\x5b\xfe\xc9\xf2\xe2\x45\xae\xdc\xf8\x78\x44\xa1\x7c\x11\xcf\x8c\x77\x2b\x0d\xba\x0a\x36\x59\x68\x89\x99\xff\xf2\x00\xef\x9c\xf5\x15\x4e\xda\x6d\xf0\x9f\x5a\x06\xff\x29\x6e\xb5\x68\xf2\x8f\xbc\x0d\x02\x7f\xa4\x97\xc9\x52\xc9\xea\xab\x95\xf4\x9f\xd3\x51\xb0\x90\x7e\xa0\x60\xb3\x96\xde\x63\x36\x97\x68\xe9\xd8\xc2\x89\x1b\x52\xb5\x86\x6c\x9d\x0c\xc9\x3c\x0e\x19\x14\xe6\x06\x9a\xfb\xc0\x5e\x0e\x5b\xfd\x74\x6b\x6b\xda\xbb\x92\x86\x9f\x4a\x14\x34\x4e\xd0\x71\x03\xc3\x39\xcc\xc5\x38\x8a\x10\x12\x65\x98\xe5\xb7\x99\xee\xb6\x70\x2a\xc6\x54\x37\xb1\x64\x2f\x12\x84\xa8\x07\xb9\x55\x2d\xf9\x13\x24\x1d\xb2\xac\x73\x02\x9d\x30\x96\x9d\x40\x9f\x4d\x56\x2b\x5d\xe7\x45\xb4\xd9\x32\x90\x1f\xc2\x11\x15\x1a\xeb\x69\x09\xe2\xe8\xb5\x0a\xc2\x36\xe9\x0b\x92\xe5\x4a\x8b\xc8\xda\x1d\xdb\x40\x3a\x59\xe8\x5b\x08\xc2\x5a\x69\xe7\x5c\x34\xae\x3e\x6b\xeb\x3a\xd9\x23\x81\x68\x4e\x55\x38\xce\x4b\x85\x82\xae\x99\x1a\xf7\x59\xb0\xb3\x66\xa2\xc6\xaf\x76\x10\x86\xee\xa7\xc7\x54\xf5\x9b\x77\xa8\x74\x47\x2e\x25\xbd\xea\x42\x56\x99\x98\xc8\x60\x79\xe6\x4c\xb2\x96\xb5\x1f\x5e\x1c\x4b\x31\xc0\x20\x6f\xe6\x22\xaf\xc1\x1a\xb9\x88\xcc\x31\x1b\xd4\x98\x14\xd6\x5d\xae\x12\xd2\x0e\xf8\x32\xac\xb2\x60\x06\x49\x9b\x00\x3d\x3b\xe6\x68\x0f\x68\x10\x8d\x4a\x9f\xd9\x1d\xb5\x61\x96\x22\x6a\xda\x72\xaa\xed\x66\x20\x40\xb7\x33\xd3\x41\xaa\x8d\x45\xcb\x62\xda\x6a\x23\x59\x86\xe8\x0c\x81\x7a\x6c\xb6\xd8\x5d\x76\xce\x96\xaa\xd5\x9d\xdb\xc5\xa9\x0e\x31\xc5\x51\x67\x0c\x4a\x04\x6c\xa8\x57\x0d\x5b\xea\x75\x9d\x82\xfe\x0d\x80\xf0\xa5\x56\xcf\x54\xac\x69\x21\x93\x61\x17\x91\xb5\x5f\xaa\xbb\x08\x5e\xc6\x52\xa4\x1e\x56\x7e\xeb\xbb\x2e\x5b\x66\xcb\x6d\x01\x66\x3c\xe4\x45\x6a\x5b\xd6\xb9\xf6\x44\xf6\xb5\xcd\x7b\x38\xce\xcb\xdb\x21\x79\x5d\xa3\x6c\xf8\xf6\x50\xff\x52\x53\xeb\x51\xcb\x85\xc0\xbc\xd7\xba\x79\x63\x2b\x3b\xcf\xe5\xdb\x60\xde\xb0\x85\x11\x23\xcc\xc0\x09\x4b\xc5\x2d\x13\x9a\x59\x72\xaf\x2e\x39\x4a\x81\x17\x1f\x4b\x79\xc5\x31\x5d\xb5\xf7\x51\x8f\xb1\x8c\xdb\x2e\xd8\xf5\x48\x14\xeb\x6b\x16\x2c\x4a\x9f\xd3\xea\x9f\x9e\xa3\x02\x6a\x2e\x41\xf7\xdb\x40\xd6\xbb\xfb\x40\x92\xd8\x92\xfb\xcc\x07\x1b\x0f\x13\x12\x78\xf7\x6f\x3d\x34\x46\x39\x45\xc3\x97\x77\x7b\x67\x87\x78\x89\xbb\x26\xed\xc1\xe1\xfb\xa3\x8f\x87\x57\xc7\x7b\x1f\xff\xd7\xc3\x43\x2b\xe8\xea\xf8\xf0\xf4\xcf\x87\x07\x4d\xcb\x5f\x9a\xab\xf0\xff\x2e\x34\xf2\x7c\x7d\x05\x90\x45\xe2\x0e\x71\xa8\xdd\x3b\x05\x6d\x93\x5e\x24\x96\x38\x72\xd0\x42\xb5\x38\x84\xba\x9d\xf6\x66\xc8\x62\xd0\x92\x94\x8f\xd1\xd3\x9c\xac\x6f\x6d\xe5\x9b\x49\x72\xa8\x6e\xd6\x33\xa9\x7f\x01\xa7\x60\x5c\x1e\xa7\x1e\x24\x9e\x53\x48\x42\x16\xaa\xb6\x8b\x81\x56\xdf\xe7\x28\x76\x6c\x41\x8b\xe7\x28\x75\x2c\xe1\xc4\xdb\xbb\x62\xc1\xc7\x01\x2c\xf4\x77\x79\x31\x82\xcd\xd4\x73\xd1\x51\xc2\x9a\x98\xa3\x46\x0d\xfc\x0d\xe1\x8f\x90\x6c\x27\x51\xa1\xbe\xde\x5b\x2e\x4a\xfc\xfa\x38\x9d\xd3\x5d\x76\x3b\x98\x24\xb2\xbe\x08\xf4\xee\x5e\x12\x34\x44\x52\x6a\xe8\xff\xa1\x04\x3e\x4f\xf6\xb1\x1b\x80\x0d\x21\x2c\x71\xff\x08\x3f\x3c\xb4\x62\x22\x5c\xa6\xfe\xd4\xbb\x54\x52\x1d\x12\x16\x45\x09\xa7\x9d\x66\x3a\xd2\x5e\x81\x24\x4b\x95\x24\x5a\x19\x37\xf4\xe5\xca\x06\x6c\x2a\xad\x09\xd5\x80\x3c\x51\xf6\xea\x68\x88\xee\x1b\x6f\x83\x99\x43\x1f\x9c\x42\x1b\x37\xf3\x48\x6e\x24\x8c\xb5\x83\x41\xb0\x77\x20\xa6\x4e\x52\xd9\xc5\x4a\x1c\x8f\xbb\x10\xf8\x1f\x74\x9e\x5d\x12\xeb\x6b\x06\x6b\xe1\x09\xb3\x5c\x83\xad\x03\x65\x09\xef\x42\x36\xf8\x43\x1c\x75\x02\xe9\xa1\xe2\xd9\xb9\xb9\xbe\x93\x74\x77\x1e\x4d\x72\x1b\x20\x64\xb8\x5a\xd2\xf9\x7c\x7a\xc7\xce\x48\xb5\x62\x11\xea\x29\x65\xfe\x98\x81\xde\x47\x0a\x0d\x71\x63\xc2\x0c\x2a\xf2\x80\xbb\xee\x7e\xa5\xea\x94\x86\x39\x9e\x3a\xf1\xa7\x42\x45\x96\x16\xdc\x47\xbb\x8a\x5d\x95\xeb\xa8\xda\xaa\xb1\x11\x19\x95\x22\x32\x37\x33\xd8\x19\x45\xc3\xba\xdb\xe5\xd0\x3c\x0b\x80\x31\x95\xda\xe1\x5d\xde\x00\x08\x43\xa3\xbd\x8c\x80\xe3\x43\xb6\x0f\x71\x3c\xc4\xa4\x77\xb3\x4c\x2b\x02\x9b\x77\x70\x15\xd1\xea\x7d\x9a\x92\x61\xc4\x76\xd0\x0b\xb6\x33\x34\xa1\xb7\x76\xc7\xd6\x99\x62\x6c\xeb\x49\x34\x34\x2b\x3c\x7a\x15\xae\xa6\x03\x29\xb7\x29\xdd\x8f\x91\x47\x05\xe2\x98\xbc\x3b\xd8\xaa\x0e\x1f\xf2\x71\xb6\x7f\x37\x9c\x66\xa4\xef\x10\xb6\x15\x1e\x3e\x94\x43\x3a\xd0\xd6\x4e\x05\x9a\xb1\x64\xf9\xe1\xa4\x60\x56\x94\xc0\xf2\xb0\x9a\x37\xfe\x8b\x98\xbb\xb6\xae\xd9\x55\x1b\x09\xf9\xda\x85\x50\x3f\x6c\x31\x04\xd7\xe1\x3d\x93\x7e\x89\x30\x8b\x1e\xa1\xaf\xc2\x7b\x49\x64\x4e\x3e\xee\x1f\xb2\x78\xd8\xa2\x3a\x1c\xe0\xec\x7e\xad\x34\x92\x82\x29\xd8\xda\xaf\xa8\x54\xb4\x9f\xa8\xa2\x1c\x22\x86\xc6\x45\x08\x67\xdf\x08\x35\xfa\xfd\x6e\xb8\xbc\x9f\xf1\x46\x21\x8b\xb0\xdf\x1d\x6f\x3c\xa8\xe0\x20\x34\x62\x65\x8d\x19\x63\x93\xf4\x2c\xf0\xee\x3f\xeb\x4c\xb4\x6f\x15\xe6\x4f\x24\x75\x10\x74\x1c\x76\xa6\xab\x7b\xcb\x97\xe4\xcd\xf6\xc9\x04\x07\xf9\x68\x6d\x3c\x66\x70\xca\x67\x44\x4f\x73\x04\x1f\x6b\xf4\x02\x91\x37\x60\x6b\x2a\xd3\x4c\xd1\xaa\xcd\xfa\x04\xb6\x2e\xb1\x9b\x44\x9e\xb5\xf5\xbd\x7f\x83\x73\x5a\x89\xd3\xe4\xde\x5a\xed\x0d\x41\xfb\xc2\xa6\x04\x70\x5c\x12\x72\x0e\xb9\xa9\xdc\x7d\x2d\xd9\x19\x14\x1a\xa3\x68\x50\x20\x10\x11\x26\xc3\x9d\x61\xe5\x99\x25\xcd\x02\x5b\x29\x92\x1b\xbc\x3c\xf1\x44\x90\xd2\xe3\x70\x6d\x5e\xbe\x6c\x9a\x39\x34\x27\x66\x33\x93\x46\x7c\xd2\x0a\xd9\x85\xdd\xad\x19\x06\x9f\xc6\xd9\xca\x5a\x47\xcd\x5c\x75\x8c\xaa\x97\x0e\xa0\x4a\xa9\x65\xe9\x7e\xc6\x7c\xc4\x6a\x85\x9a\x4e\xd2\x59\x08\xaf\x13\x37\xd9\xac\x27\x11\x42\x4f\xad\x34\xca\xd3\xb7\xc8\x50\x48\x2b\x13\xec\x4b\x03\x7c\x8e\xcc\xe8\x26\x47\xaa\xc8\xb7\xa1\x42\x47\xd8\x48\xbe\xcf\xd7\x5b\x3c\xfb\x24\xb8\x55\x50\x5a\xd3\x3b\xfa\x1a\xa8\x9b\x22\xdd\x74\xd9\xe4\xeb\x58\x5d\x87\x33\x19\xff\xc4\x0a\xca\x76\xaf\xcd\xf2\xd4\x4a\xf3\xb4\x6c\x57\xe2\x38\xb1\x1a\xbc\x1a\xdc\x84\xc7\x16\x14\x84\x65\x3a\x2e\xce\x98\xfb\x3a\x51\xae\xb4\x59\xb9\xab\xad\x6e\xda\x18\x71\xd2\xdc\x6f\xed\xc6\x5b\x5b\xd2\x57\xbb\x30\xb6\x60\xea\x5c\x3f\x54\x52\x0a\x7e\xc5\x29\x91\x25\x5a\xfc\x65\x4c\x17\x6c\x8a\xb9\xeb\x0b\x0c\x25\x34\x16\x1c\x65\x9a\xec\x5e\x01\x3c\x7a\x0b\xb8\xcd\x29\x0f\x4f\x90\xba\xf1\x09\x6a\xda\x1e\x0b\x2b\xc4\x66\x1b\xa0\xa6\x5f\x95\x70\x24\xcc\x99\xdf\x61\x55\xfd\x08\xfd\x67\x66\x34\x0a\xcd\x95\x82\xd0\xd0\xca\xfd\x04\x2f\xb0\x56\x92\x30\xc2\xe3\x96\x5d\xa8\xd4\xf8\x73\x59\xd5\xfd\xc8\x4a\x42\x8e\xc5\x43\x37\x20\x91\xf2\x48\xa5\xc7\x4d\x2d\xca\x44\xb6\x6a\xdf\xbf\xb6\x15\xed\xbe\x6a\xd5\x5e\x47\x32\x76\xb2\x06\x96\x62\x9d\x2e\x53\x97\xde\x92\x5f\xd7\xc8\x30\x48\x10\xfe\x7d\x4b\xcb\xe8\x98\x3c\xf7\xbc\x32\x1f\x18\xf6\x08\x82\x5f\xb5\x74\x8a\x5c\xf6\x27\xee\x7f\xb7\xd3\x99\x84\xa2\x4d\xc6\x36\x7b\x14\xf7\xbf\xdf\xf1\xbb\x91\x76\xf1\xee\x5d\xcf\x12\x3e\xe9\xc1\x73\xcc\x8c\xf4\x62\xf2\xaf\x95\x95\x12\x6d\xf9\x39\x3a\x23\x43\xd7\x9c\xdb\xc0\x65\xca\x56\x16\x04\x0c\x5e\x73\xd3\x0a\x4a\x9a\x74\xb8\x7d\x96\xf2\x82\x61\x2f\xb4\x45\x2b\x61\x9d\x6b\x82\xd7\xa2\xc8\xf9\x1a\x82\x67\xd5\x07\xe6\xfb\x30\xe3\x06\xb9\x80\xed\xea\xf3\xf7\x26\x81\xa2\x2b\x9d\x99\xc3\x54\x1e\xb4\xf0\x55\x9e\x31\xca\xcd\x51\x7c\x86\x21\x90\x52\xc9\x3b\x3a\x38\x81\x33\x8b\x66\xd4\xed\x61\x53\x0a\xce\x65\x72\x2f\x61\xac\x95\x10\x8a\x6b\x87\xc0\xe5\x96\xd3\xae\x4f\xde\x34\x6a\xb7\x70\x7d\x79\x91\x52\x6b\xd5\x7b\xcc\xe5\x17\x69\xb6\x4a\xd1\xf8\xd1\x01\x3a\xd4\xb2\x74\x1d\x63\xb7\xfb\x09\x2d\xfb\xe8\x20\x6c\xf8\xec\x2a\xad\x4e\x6d\x36\x37\x7e\x63\xc8\x81\xd1\x08\x84\x8e\x7c\xf3\x0c\xd7\x01\xae\xb5\xcb\x66\x1f\xbb\xab\xb3\xca\x12\x0d\xa1\xab\x47\x24\xbe\x82\xb7\xaf\xfd\x5a\x2a\x5d\xfd\x51\xa1\x8c\x42\x94\xbd\xae\x9a\x00\x0f\xd5\x15\x25\xca\x5e\x67\x0d\x93\x45\x77\x1c\x7c\xe7\xaf\x3a\x8b\xe2\x7c\x73\x23\xa7\xcb\x54\xcf\x70\xb5\xcc\x19\xde\x3c\x03\x45\xdc\xc6\xb5\x74\xef\x99\x7a\x57\xe4\x79\x49\x62\x06\xb3\x74\x51\xc9\x06\x10\xab\x14\x88\x31\x3b\x4d\x57\x32\x8d\x60\x83\x8c\x50\xc9\xc0\x56\x5a\xe0\x32\xfe\xc6\x06\x90\x96\xdf\x82\xed\x62\x3b\xf8\xad\x17\xac\x94\xa7\xd7\x96\xd1\xa5\xde\x7a\xbc\x2e\x17\x1b\xa6\x11\x8e\x11\x85\x7b\x80\x77\xd4\x18\xb5\x69\xc4\xf2\xc9\xa6\x11\xce\x31\xde\xb5\xb4\xb0\xcf\xf1\x53\x2b\xfc\x63\xba\xb0\xaf\xdf\x02\xd7\xb0\x42\x1a\x3a\xd8\x52\x79\xdf\xb9\x7f\xb2\x4e\x30\xd0\x3e\xfa\xdb\x97\xb0\xae\x1c\x42\xce\x18\x23\x83\x68\xca\x03\x66\x96\x1d\x23\xc7\x19\x7b\x0b\x7b\x89\xde\x3d\xe1\x7a\xf6\xaa\x25\x26\xe8\xa3\x28\xe1\x5e\x33\x5a\xae\x26\x18\xf1\x95\xee\x44\xd3\x80\x6a\x88\x3d\x86\x4b\x05\x96\x0e\xe3\x80\x50\xa8\xb2\x37\xb2\xc3\x50\x51\x0a\x0a\x53\x19\xb4\x63\x68\xc7\xa2\x1d\xc1\x13\x69\x9f\x33\x90\x08\x39\x91\xd6\x96\x64\xe2\x78\x3a\x67\xe6\x88\x6c\xe7\xaa\x36\x73\x2b\x88\x88\x05\xc1\x90\x26\x3b\xaa\x19\xb5\xd2\x74\x6b\x15\xa9\xf6\x39\x89\xc6\x2b\xdc\xdb\xcd\xd6\x4d\x77\xa3\xd4\x76\x91\x57\xdb\xdb\xed\x1e\xd5\x68\xf9\x5c\x32\xd3\x18\x73\xe4\x68\xad\x7e\xe2\x57\x22\x05\xce\xa6\x3e\x90\x0b\xd0\xff\x89\xaa\x13\xae\xd9\x29\xd2\x08\xdd\x06\x3a\x74\x20\xe6\xb9\xf2\xfb\xed\xf9\x1c\xd7\x34\x5b\xc6\xa1\x4d\xdc\x20\x95\x1c\x53\x25\x52\xcd\x2e\xe5\x74\x9d\x36\xae\x93\x59\x73\x6e\xa4\x62\x89\xdc\x0f\x1a\xdc\xd1\x81\x8f\x6f\xff\x52\x3e\x15\x0c\xb4\xec\xb7\x26\x8b\x59\x3e\x2a\x70\x6f\xc3\xbc\x6f\x73\x47\x75\xeb\x98\x51\xab\x63\xc6\xbf\x7a\x82\x51\x4d\xe7\x62\x8c\xde\xe8\xba\x8f\xa5\x83\x35\x71\x6c\x28\xb8\xa8\xee\xee\xb1\xa3\x9a\x12\x23\x6a\x70\x3b\x38\xec\x6c\x8e\xd5\x43\xee\x54\xb1\x12\x86\x72\x70\xcc\xd0\x44\x6c\x4b\x46\x1f\x30\xd2\x01\xe1\x27\x8d\x6c\xc9\x17\xea\x3d\x8e\x13\x7b\x41\x99\x64\xfa\x2a\x7f\x1e\xad\xc6\x79\x01\x0b\xe2\xee\x7e\x5d\x9b\x47\xab\xae\x85\x69\x4f\x0c\xcf\x55\x7e\x38\x16\xde\xb9\x8b\x23\x1f\x29\x87\x7e\xbd\xa6\xe6\x82\xbf\x2c\x32\xee\x94\xab\x2f\x03\x86\xca\x6d\x2c\xba\x41\xd1\x72\xfc\x5e\x4b\x54\x87\xa6\x98\xd0\x53\x86\x9f\x82\xa7\xd1\x5d\x18\x29\xe6\x37\xf4\x7c\x83\xde\x6b\x6f\x57\x2d\xdb\xa2\xb6\xec\xc3\x5d\x1d\xe4\x03\xb1\xe7\x93\xbe\x69\x90\x6c\xd3\xd5\x32\xa6\x63\xf2\xb5\x63\xcd\xf4\xf3\x17\x11\x7a\x07\xd4\x93\x4f\xb6\x5a\x4d\x3c\x4a\x23\xfe\xae\x8f\x9e\x42\x98\xff\xf7\xec\x05\x5e\xa2\xfd\xe8\xbe\xe4\xd9\x24\x9a\xdb\xdd\x52\xe1\x51\xa0\x8a\xf2\x95\x92\x43\x1d\xa1\xaa\x3f\xf4\x9f\xd7\x89\x90\xaf\xd4\x87\x07\xdf\x04\x1f\x78\x2b\x58\xb3\xe1\x22\x99\xc9\x59\x32\xa8\x42\xdc\xa2\x94\xaf\x90\xab\x7c\x81\xfc\x85\x9a\x97\xd6\x69\x8d\xce\x7b\x57\xb3\xb4\xfe\xa2\x64\xdb\x6d\xb1\x92\x62\x1e\x03\x76\xba\x6d\x9d\x35\x3b\x57\xa1\x52\x70\xb4\xe5\x46\xbe\x84\x8e\x6c\x94\x34\xaf\x0a\xf3\x6d\x86\xb7\x68\x1a\x88\x9e\x7d\x51\x23\xbc\x7c\x82\xee\xcc\xb5\x4c\x05\xaa\xef\x6e\x6c\x3e\x7f\x1c\xbc\xc0\x4d\x2b\xad\x4b\x31\xcc\xa0\x8b\xdc\x75\x66\xa5\x96\xa5\x90\x9c\xb4\xfd\x91\xa4\x0a\x0e\x25\x91\x4c\xf6\xbd\x67\xa3\x72\xe4\x59\x6d\x91\x73\xd4\xec\x81\x9b\xb0\x62\x9f\x1f\x8f\x7c\xa6\xef\xfc\x5c\x3f\x1c\x2d\x2a\xd7\x98\x94\xaa\x57\x76\x69\xfa\x60\x50\xbc\x30\x5d\xdc\x94\x81\xda\xd6\xa0\x57\x04\x0e\xf3\xc9\x2b\x7f\x36\xa0\xe6\x4a\x5a\x28\xcf\x1e\x8e\x07\x22\xbf\x0f\x97\x52\x5e\x2e\xa6\x44\xa1\x6e\x42\x9f\xd0\xe3\xa2\xbc\xa4\xf3\x04\xfc\x86\x99\x28\x05\x5e\xb9\xae\x86\xa8\x8c\x0a\xdb\xfe\x7d\x9a\xd4\x2b\xd4\x28\xb2\xcd\xf0\x49\xc0\x15\xdd\xdf\x2b\x73\xb1\x82\xbc\x76\xe3\x62\x59\x91\x3f\x3e\x57\x19\xaf\x43\x55\xd1\x37\xaf\x35\xbb\x25\xa7\xb6\x7f\xd5\x1a\x1a\xd2\xb8\x2e\x81\xea\x23\xe2\x02\x35\x40\x40\x07\x20\x76\x12\xaf\xd7\xa3\xf1\xc7\x0c\xc7\x20\xad\xee\x9c\x11\x60\x18\x0c\x5f\x29\x08\x73\xda\x52\x2b\x64\x41\xcc\x93\x89\x8e\x58\xb8\xd4\x2f\x12\x12\x77\x23\xe9\x20\xd0\x2a\x9b\x36\xfd\x8d\xb6\xb6\xbc\x2d\x5e\x78\xb7\xf3\xb5\x81\x52\xf5\xcb\xad\x19\x4c\x41\x3c\xc1\x1c\x8d\xe5\xcc\xae\x0f\xf2\xf1\xb8\xe5\xba\x6d\xe1\xa5\x06\xc2\x47\x24\xb2\x36\x96\x49\xef\x4b\x76\x57\x43\x44\xaf\x86\xe3\x7b\x88\xfa\x02\xa1\x3b\xa3\x1f\x1e\x02\xc3\xad\xd4\xb9\xd5\xce\x40\xec\xc0\xaa\xd4\x5e\x49\xc8\x61\xc6\x3d\xb9\xc6\x58\xb5\xee\xcc\xd6\xc3\x5a\x58\xf4\x07\x21\x2c\x54\x6f\xd4\x49\xc9\xd4\x7e\x90\xc1\xf0\x14\xe4\xcb\xcd\xcb\xf9\x17\xd6\x68\xd6\xbe\xd3\x44\xa1\x8e\x0e\xa5\xcb\x0f\xd8\xf7\x8f\xa8\xa0\xd3\x19\x19\x02\x5f\x29\x35\x93\x96\x6b\x78\x50\x4c\x85\x87\xf3\x8e\x09\xf3\xf0\xb0\x59\xf6\xbc\x17\x9b\x0f\x0f\x1d\x11\x90\xe5\x12\x32\x1d\x0c\x77\xc3\xa7\xb0\x01\xb4\xbc\x9a\x59\x14\x82\x32\xc1\x55\x18\x45\xb1\xf7\xa0\xa3\x8f\x6c\xe6\x58\x23\xfb\x3e\xa9\xe1\x89\x79\xef\xa5\xd0\x63\x93\xa4\x91\x45\x44\xad\x2e\x58\xc3\x12\xe8\x31\xae\xba\x96\x9a\x39\xd9\xb5\x19\xa1\x81\xc6\xf9\x7e\x0a\x97\xd4\xe4\xaf\x36\x8d\x42\x8b\x3c\x7f\x41\x76\xf9\xd6\x56\x1f\xa8\x64\xa5\x30\x54\x94\x1a\xcc\xc5\xce\xa5\xa1\xe3\x09\xed\x1b\xf9\x2e\x86\xc6\xf2\x63\xc2\xa8\xde\xed\xc7\x3b\x83\xf4\x67\xf5\xf5\x20\x55\x56\x4f\xac\xbf\x3d\xb8\x0d\x4b\xe1\x21\xed\xf5\x6e\xad\xd0\x6f\x4a\xde\x8e\x6a\xe5\xd3\x6d\xa3\xc4\x3e\xf5\x8e\xa1\x67\x01\x09\x0d\x14\xd4\xe8\x5e\x3c\x63\x32\x93\xb4\x54\xa7\x4d\xf2\x34\xaf\xe8\x77\xe3\xec\xc5\x05\x6c\x6d\x79\x83\x43\xd6\x02\xf5\xd2\xae\xa4\x41\xaf\x92\x52\xa8\x03\x32\xac\x63\x75\xf9\x65\x1d\x95\x2b\x99\x7e\x29\xa5\x36\x0d\x36\x39\x24\xfd\x5d\xf7\x88\xa1\x2a\x97\x3f\xe7\x5c\xc2\x1f\xf1\xe5\x59\x4a\x73\x7f\x88\xa0\x6f\xd0\xb9\x1d\x25\xaf\x99\xb4\xed\x03\x16\x82\x0c\x75\x6d\x91\x9d\xc7\x4c\x12\x19\xae\x3f\x65\xe6\xc4\x53\xdd\x85\x15\xea\xc1\x79\xf6\x39\x9e\x2f\x5d\x47\xbb\x0c\xd7\xb6\xad\x9c\xd8\xe4\xe7\xd1\x95\x9e\xfd\x3e\xf0\x1c\x6c\x8a\xee\x23\xcc\x63\x47\xd8\xf2\xb1\x23\xec\xf2\xe9\x47\xd8\xf4\xd1\x76\xaa\x2f\x3b\x24\xd9\x48\x34\xf1\x42\xba\x3b\x45\x53\xfd\xa2\x5b\x2a\x2e\x91\xa1\x3a\xc7\xed\x57\x06\x80\x24\x41\xef\x49\xd5\xe2\x41\xfd\xa7\x5f\xdc\x9d\xe5\x0d\x6c\xe8\x30\xee\x5d\xa5\xb4\x19\x77\xe0\xd4\x4b\x75\x76\x1d\xe8\xa7\xa4\xab\xdf\xd6\x0a\xc7\xf0\x06\x2d\x75\xb2\x20\xd6\x34\x7b\x64\xca\x7a\x9b\x0e\xed\xf9\x8f\xff\xd0\xc7\x6b\x53\xb1\xc2\x2a\x81\x58\x77\xd9\xea\x1b\xa9\x71\x88\x38\x4d\x19\xfc\x6c\xf6\x1f\x1e\x6a\x8f\x56\x30\xde\x31\xb3\xbb\x0d\x04\x41\xee\x5c\xb0\xa8\xfc\xbe\xbc\x9e\xe6\x43\x75\x86\x27\x9e\xa6\x60\x11\x5d\x92\xcc\x76\xe5\xe3\xfd\x2a\xe6\x27\x76\xaa\x9b\xf9\x3e\x44\xdf\xb7\xed\x02\x9d\x83\x93\xe7\x2b\xce\x55\xbb\xdc\x5b\xb0\xd7\x0a\x57\x33\xc8\x9d\x15\x9e\x35\x23\x9a\x07\x33\xc9\x6a\xea\x77\xfb\xb4\x64\x1c\x76\x59\xaa\x46\xd0\x9b\x78\x70\x73\x42\x16\xbd\xc2\xc4\xf0\x23\x9f\xa2\x5a\xcd\xf0\xe0\x50\xb8\xe5\xc3\x5c\xed\x24\x06\xac\x35\x37\x98\x2b\xc0\x21\x46\x87\xaf\xc3\x6b\xd1\xcd\x4a\xde\x37\xc4\x47\x81\xfb\x1e\xb4\x38\xca\xa0\x11\x10\xac\x59\x3c\x41\x67\x54\xb0\x62\xea\x74\xa8\x70\x79\xaf\xed\xcb\xac\xc3\x27\x6b\x26\x38\x10\x2e\x6f\xec\x04\xcf\x00\x5c\xf9\x27\x40\x52\x9e\xaa\xbe\xd0\xbc\x14\x82\x48\x83\x19\xd3\x8d\xa0\xf2\xc7\xb5\x1d\xba\xc0\x56\xd4\x7d\x50\xdc\xff\xbe\x2f\x1a\xf7\x3e\x71\xff\xf5\x1b\xff\x7d\xf9\x23\xb6\x4e\x9e\x2b\xf5\x37\xcf\x80\x51\x6b\x5e\x49\xe5\xbe\x2b\xa9\xb2\x75\xb7\x74\x2f\xd7\x6f\x9c\x3b\x88\x48\x1e\x12\x05\x39\xfa\x68\x76\x45\x1c\x26\x10\x61\xa2\xba\x45\x92\x59\xf2\x49\x93\xca\x40\x06\xae\x1c\xdb\xce\x72\xcd\x24\xf5\xf5\x6a\xb3\x83\x9e\x06\x5c\xa3\x1b\xc9\x6b\xbb\x85\x2f\xf9\xe6\x0f\xe1\xce\xe4\x2e\x6c\x19\x4a\x19\x9b\x37\xb0\xe6\xb6\xb4\x7c\xca\x6d\xe9\x2c\x9d\xab\xa1\x42\x2e\xbd\x0c\xef\xd3\x38\x48\x03\x91\x5e\x5f\x57\xf0\x00\xff\xe1\x79\x34\x62\xe0\x0f\xf9\x00\x21\x50\x0b\x78\x85\xff\xf8\xbc\xc8\x61\xdd\xe0\x2b\x3d\x40\x48\x9d\x8f\xf0\x1d\x7f\x10\x77\x1e\xf1\xbd\x03\xfa\x09\xc4\x75\x1c\x5c\xc3\xff\xb4\x86\x04\xf8\x1f\x9e\x47\x39\x3c\x8e\x72\x7c\x2a\xf1\x09\x53\xe5\x37\xf0\x94\xdf\xc0\xd3\xb4\x1c\x7e\xf9\x7d\x59\x22\xb6\x87\x79\x86\xf0\x72\x74\x07\x21\xf0\x1f\x9e\x11\x73\x06\xea\x29\x21\xc7\x03\xfe\x0d\xd0\xc1\xd4\x6d\x0a\xd5\xe6\x5f\x7c\x9f\x93\x2a\x41\x20\x1f\x20\x24\x27\x94\x98\x1c\x73\x1c\x22\x9c\x50\x80\xff\xf1\x79\x8a\x8f\x53\x7a\xba\x61\xe0\x7b\xf5\x14\xb0\xf7\x90\x00\xff\xf3\x33\x79\xc5\x08\xd4\x13\x84\x21\xf0\xcb\x28\x40\xcb\x63\x78\x40\x44\x04\xdc\x17\xf3\x69\x8d\x6f\xf4\x00\x21\x63\xa8\x07\xfc\x83\xa7\x3c\x9d\x96\x08\x1e\x43\xbf\xf8\x7e\x8b\x2f\xb7\xf0\x84\x9f\xe3\xd7\x98\x3b\xe4\x9b\xcd\xe2\x20\x9b\xe1\xef\x75\x36\xc2\x47\xf8\x09\x04\xe1\x60\x93\x9f\x02\xf5\x84\x61\x37\xba\xb1\xe6\x99\xc2\x61\x7f\xa1\x30\x72\x62\x33\x06\xf6\x36\x23\xb7\x05\x25\x81\xd1\x90\xf7\x12\x74\x62\x00\xa5\x4c\xfa\x71\x30\xe9\xc3\xef\x2b\xf8\x7d\x05\xbf\xdf\xc1\xef\x77\xf0\xfb\x3d\xfc\x7e\x0f\xbf\x3f\xc0\xef\x0f\xf0\xfb\x1a\x7e\x5f\x07\xe4\x9e\x04\x9e\xe0\x7f\x20\x5d\x95\xf0\x1b\xe6\x3b\xc1\xe7\x8a\xfd\x24\xa0\x53\x84\x19\xb4\x0a\x46\x1d\xc6\x3c\x27\x1f\x27\xf0\x48\xbf\xf0\x3e\x83\xae\x80\x7f\xf0\xe4\xa0\xd2\xa0\x0a\x30\x3c\x43\xcf\x7d\xb9\x86\x62\xe0\x1f\x3c\x65\x77\x37\x19\xa3\xd4\xc0\x6f\x20\x5d\x96\x04\xf4\x03\x6f\x19\x22\xef\xc0\x6b\xc6\x08\x3c\x53\x28\x70\x9a\xe3\x6f\xf1\x05\x9f\x8a\x2f\x81\x98\xa5\x39\xc2\xd4\xa4\x88\x5f\x80\x46\x6c\xf0\x38\xc7\xa7\xea\x0b\x3e\x56\x98\x82\x40\x82\x18\x1d\x08\xff\xa3\x57\x09\x7e\xc7\x27\x0c\xc3\xb9\x80\xff\xe9\x99\xc0\x6a\x32\xea\xcb\x22\x85\x71\x84\x7f\xf0\x54\xd6\xc3\x2a\x9f\x43\x63\xd4\x53\x20\x58\x0a\x1c\x2b\x69\xb0\xc0\x09\x87\xf3\xad\x9c\x2f\xe4\x7c\x53\x4f\x14\x46\x23\x59\xca\x51\x04\x1e\x92\xba\x86\x7f\x03\x01\x89\x21\xd5\x3c\x85\x1e\x44\x00\x1c\xf8\x81\xb7\x9c\xfc\x14\xc1\x7b\x2e\x1d\x16\xcd\xe9\x8d\x9f\xca\x1b\x5e\xd0\xea\x29\x10\xbf\xc7\xc1\xef\x81\xa8\xd0\xc1\x03\xe4\x85\xa8\x34\x88\x46\x53\x2d\xaf\x61\x95\xe1\xff\x40\x40\x72\x48\x57\xa7\x33\x48\x83\xff\x03\xa1\x5a\xa5\xda\x54\x4b\x55\x9d\x40\x3e\x04\xd2\x45\x89\xc2\xd9\x81\xf7\x59\x4a\x90\x3c\xf8\x03\x6f\xe5\xb2\x1a\x22\x0a\x0f\xfd\x06\xec\xa7\x24\xc0\xff\xf0\xbc\x00\xf6\x00\xa6\x02\xff\x06\xd2\xff\x48\x40\x3f\x01\x7a\x08\x80\xe7\xe5\x35\x3e\xcd\x66\x28\x10\x0d\xe4\x03\x86\x60\x05\x09\x15\x88\x5c\x7c\x04\xf4\x03\x6f\x4c\x32\x16\x4c\x33\x16\x88\xd4\x83\x18\x3d\xb0\xf5\x30\x35\x53\x4f\x10\x86\xcb\x01\x02\xf0\x07\xde\x26\xf0\x38\xc1\x5f\x9a\xe0\x0b\x9e\xe1\x0b\xf4\x19\x14\xe0\xff\x40\xba\x3d\x09\xe8\x07\xde\x60\x0a\x2c\x10\xa8\xa8\x4a\x11\x26\x8a\x7e\x80\x1d\x03\x06\x0c\xfe\x43\xe3\x97\xd0\xf2\x00\xa8\x76\x10\xd3\x7f\x81\xc0\xf9\x40\xf7\xe8\x27\x10\x5f\x91\x98\x7d\x45\x6a\x36\xcc\x2b\x22\xab\xfc\x8b\x5e\x47\xf2\xf9\xa7\x14\x6b\xa3\x9e\x90\xae\x8c\x89\xa8\x8c\x61\x64\xb2\x29\x04\x23\x59\x95\x0f\x81\x80\xee\xbb\xa1\xf9\x9e\xd1\x7c\xcf\xf8\x39\xad\xfe\x8c\x2e\x17\x88\xcf\x73\xdf\x71\xe6\xd7\x34\xf3\xeb\x2f\x38\x9f\xb0\xac\x39\x95\xa3\x9c\xe5\x04\xf2\x01\x42\xca\xe9\xdd\x0d\x8e\xb5\x7c\xe0\x10\x2e\x4b\x3d\xb1\xe3\x90\x74\x6a\xca\x73\xdf\x03\xc1\xce\x4b\xd8\x6b\x49\xbd\x40\x94\x2a\xfc\x0f\xcf\xb7\x38\xf4\xb7\x37\x3c\x3e\x3c\x36\xf0\xcc\x13\x84\x7e\x82\x15\x5a\xfd\xb6\x90\xb2\xff\x00\x5f\x68\x76\xc0\xb8\xff\xe6\x35\x6e\xcd\xcf\x80\x52\xd8\x53\xae\x56\x14\xbe\x9a\x07\x81\x5e\xf3\x5c\x2a\x8d\xa3\x0d\x25\xcd\x7d\x53\xef\x16\x5e\xb7\x2d\x7c\x50\x46\xe5\x32\x01\x6a\xbf\x43\x49\x6a\x1d\xde\x97\x05\x03\x94\x21\x80\x4a\x61\x23\x96\x51\x80\x41\xe7\x32\xaf\x84\x4f\x65\x5e\x3f\xcf\xf9\x85\xbe\x92\x48\x24\xad\xdc\x9c\x70\x9d\x69\x3b\x14\xf3\x6e\x87\x7e\x9e\x9b\xb0\x15\x99\x7b\xda\x40\xa5\xa1\x63\x1e\x12\x28\x55\xc6\x77\x72\x5b\x5f\xa4\x37\x1c\xf1\xee\xf3\xf9\xf9\xc9\xc7\x40\x59\x88\x5c\x54\x02\x7d\x78\xb3\x15\x4e\xeb\xe8\x68\x5d\x25\xb2\xb9\x9b\x56\xe8\x8d\x36\xcd\x73\xdb\xb0\x4d\x5e\x67\x70\xac\x72\x82\xb1\xb5\x35\x24\x77\x19\x21\x99\xb5\x99\x04\xf0\x66\xd0\x11\xd4\xbd\x86\xf2\x9c\xc0\xaa\x80\x91\xcb\x8d\x4e\x79\xde\x36\xe6\x51\xfc\x83\xe1\xfc\xfd\xb3\x28\xfe\xc9\x9c\x83\xda\x68\x96\xcd\x15\xe0\x6a\x47\xe3\x1c\x7f\x0e\xc4\x01\x39\xaf\x95\xb7\x3e\x0b\x5b\x87\xf5\x0c\x95\xfe\xe1\x54\xf6\xcb\xf9\xf1\x07\x48\x71\xa3\x7d\xdb\xe8\xc6\xfa\x34\x73\xd6\x64\x11\x5c\x5d\x11\x73\x40\xe6\x88\x1d\xa9\xd0\x44\x4e\x17\x44\xfb\xc1\xc3\x83\xa7\x0c\x8a\x89\xda\xce\x95\x0d\x14\xc1\xb8\x87\x78\x90\xfa\xd8\x09\x4c\x40\x56\xbd\x2f\x2b\x52\xa9\x25\x71\xb7\xba\x72\xc9\x7b\x05\x70\x85\x78\x68\x4b\x92\x64\x7f\x37\xef\x91\x52\xe5\x81\x74\x36\x18\xe7\x83\x6b\xbc\x73\x44\x35\x6e\x92\x0b\x68\x68\x1a\x92\xa7\x1b\xa9\xab\x15\xa3\x20\x7d\x6c\x73\xdd\xe8\xfe\x9c\x05\xdd\x27\x70\xb2\x81\xa9\x85\xe6\x20\xe8\x33\x30\xc4\xab\xfb\x13\x14\xba\x20\x66\x91\x6d\x69\x4b\xd6\x39\x4a\x04\x09\xab\xc2\x28\xe1\x29\x11\xa1\x1c\x06\x47\xbd\xa1\xca\x6e\x73\xe8\xd4\x33\xec\x1f\x04\x3b\x5c\xa3\xce\xb0\x62\xf1\x3c\xd1\xa0\xfd\xb3\x33\xb5\x2a\x1c\x05\xea\xa5\xcf\x61\xe5\xb0\x15\xe8\x7c\x33\x6d\x13\xc9\x86\x9b\x0e\xaf\xd1\xa7\x4a\xea\xa8\x96\x8e\x3d\x0a\xdc\xb6\xa5\xe7\x31\x7a\x8a\x93\xc8\xd0\x8e\x86\xa5\xd4\xe8\x7c\x44\xbd\xb2\x06\xde\x39\xb3\xdc\x7a\xc2\x04\x91\xd5\xe8\x52\xb7\x0c\xbb\x00\x33\x6d\xcb\x4c\x9f\xce\xe5\xb4\x81\x5c\x84\x2a\x98\xd3\x9e\xc2\xa3\x13\x87\xf0\xd2\x85\x9b\xf4\x2d\xb9\x67\xdd\x0c\xa4\xb1\xc5\x12\x0e\x06\x15\xb9\x4f\xfa\x9a\xdc\x85\xf7\xc6\x75\x1b\x90\xda\xfd\xa4\x2f\x4e\x79\xc8\xcf\x92\x7b\xe2\x7c\xe0\x13\x3a\x8f\xe1\x6f\x45\x0e\x9b\x80\x19\x85\x1f\x3e\x66\xa0\xaf\xa6\x8a\x5d\x37\x51\xee\xcc\x96\xc3\x83\xe4\xbe\xe1\x89\x38\x6a\xf8\x25\x5e\x18\x7e\x99\x13\x45\x47\x4e\xcc\xe0\xc1\x13\x33\x43\xf0\xf0\xf5\x9a\x6b\x76\x9c\xbc\xfc\x1f\xf4\x79\xb9\xf7\xe2\xff\xbd\x94\xbf\xf1\xd5\xdf\x7a\x7f\x7b\xf1\xb7\x11\x3a\xc0\x14\x27\x88\xce\x71\x0e\xff\x1a\x14\x79\x90\x3a\xf6\x81\x7a\x73\xb0\xe4\x5a\x69\x8f\x48\xe4\xf3\xd4\x57\x9f\xa8\xb1\x69\x2b\x63\x8a\x6a\x9d\xd6\xa5\xb4\x03\x3f\xbb\xd0\xcb\xf3\x72\x37\x00\x9e\xef\xe7\x97\xc1\xb6\x0e\xda\x0e\xde\x06\xae\xff\x5a\xde\x06\x61\xb5\x14\xe7\xe9\x0d\x4b\xd5\xf7\x8a\x91\x45\x3a\xf0\xf2\x79\xdb\x4e\x2b\x27\x26\xa7\x25\x70\x97\xed\x1c\x95\x31\x1e\xcd\xa8\x53\xb9\xc5\xd7\x1e\x51\x24\xc1\xcf\x56\xcd\x5d\xad\x14\x3f\x70\x44\x15\x19\xc4\x88\xca\xf1\xd8\x01\x8f\x87\x9e\xd4\x79\xd8\xec\x65\x51\xe1\x2d\x8e\xbc\xa8\xa9\x80\xfc\x7e\x85\x7d\x06\xbd\xde\x97\x49\x17\x39\xa3\xfb\xc7\x4c\xd1\x7f\x60\xb6\x6a\xc9\x5b\x70\x27\xc0\x02\xa6\xb4\x35\xea\x95\x48\xef\xc3\xc3\x66\x0a\x53\x29\x84\xb0\x40\x84\x87\x62\x3b\x09\x36\x82\xed\x14\xb6\x6f\xd2\x51\xf1\x01\x86\xeb\x2b\x53\x1a\x56\xbe\xc4\x69\x65\x8d\xdb\x4b\xa3\x91\x46\x57\x67\x1b\xcb\x58\xe2\xe7\x7a\x04\x9d\xe1\xf5\xca\xf1\x83\x60\x10\x06\x48\x26\x58\x37\x2b\xd1\x63\x04\xfb\x22\x9e\xf7\x1a\x41\xfa\x9c\x63\x87\x93\x63\x94\x24\xf8\x1b\x90\x3e\x47\xc7\xd8\x3b\x15\xd0\x75\x47\xc7\xe6\x6c\x06\x39\xd7\xc8\x3b\xf0\xdc\xe3\x7d\xdd\x74\x90\x0a\x59\xe9\x1b\xb8\x32\xf9\x76\x21\x37\xef\x4a\xf3\x0f\x97\xbb\xe6\x59\xfa\x84\x4c\xe4\x1c\x62\x3f\x64\x26\xda\x9e\x5e\xba\x98\x19\x7a\x83\xd1\x11\x1a\x51\x88\xda\xe6\x00\x57\xb1\x97\x0f\x6b\x20\xea\xde\xdf\xcb\xbc\x08\x83\xc0\xf6\x12\xf3\xcf\xa8\x05\x0d\xd6\x5d\x09\xfb\x75\x80\x50\x03\xe8\x11\xc5\x90\x3c\xba\x5f\x4b\x85\x9c\x1b\x64\xb3\x1d\xe7\x30\xfd\x33\xad\x19\xd8\x4c\xa4\x3b\x45\x27\x21\x07\x27\xbe\x5c\xbc\x52\x5b\x5c\xb3\xe9\x9a\x09\x44\xb4\xa3\xd0\x0a\x5f\x9b\xa9\x0f\xee\xa3\xa5\x06\x56\x44\x98\x18\xd5\xb4\xbe\x3a\xe3\xd8\x26\x01\x94\x3f\xd1\xa5\x3a\x6a\x71\xf4\x55\x44\xd4\xa3\x7c\x78\x00\x32\x51\xa2\x36\x61\x10\xa8\x0b\x52\x3f\x6f\xc4\x18\x2b\x2d\x7a\x55\x44\xbb\x57\x6d\x7a\x55\x44\x71\xb8\xec\xe5\x90\x45\x5a\x8c\xd2\x6a\x84\xbb\x14\x19\x86\x62\x60\xc3\x47\x34\x36\x09\x61\x79\x78\xdb\x57\x19\xf3\x25\x6a\x3b\x5f\xd3\x6b\x72\x1e\x0f\x93\x14\x72\x06\x66\x8a\xfa\x64\xb7\xa3\x09\xf1\x42\xe2\xbc\x78\x7b\x79\xb8\x99\x24\x53\xd3\xaf\x08\x6f\xb3\x3b\x5c\x4f\x5a\x87\x51\xbc\x96\x93\x9c\x32\xae\x08\xf5\xff\x34\xda\x9c\xb6\x07\xe0\xe1\x61\x08\x25\xfb\xc2\xdb\x03\xa3\xb3\x1a\x46\x9e\x2f\xb6\xb6\xa6\x90\x10\xda\x30\x84\x9f\xe6\xb8\x62\x98\x04\xc8\x29\x93\xe1\xa0\x73\x14\x3d\xbb\x4e\x21\x86\xa8\x69\xf2\xec\x91\xe4\x15\xf2\xc8\x48\x42\x0f\xae\x4a\x93\x9a\x77\x23\x7f\xda\xd2\x59\x76\x8f\xe0\x26\xae\xa5\xd8\x9a\xb8\x2e\x2c\xe2\xba\x68\x10\xd7\x27\xd3\xe0\x35\x47\xb8\xce\x28\x49\xf1\x45\xdd\xbd\x7b\x20\xb6\xe1\x23\x5f\x2f\x25\xfd\xcf\x99\xfe\x9b\x16\x20\x92\x94\x7f\x67\xc0\x15\xc2\xdf\xf0\xf5\x2d\x6c\x04\x70\xbe\x90\x89\x55\x50\x3d\xe0\xdf\xa5\xf2\xc4\x3a\xdc\xb5\x29\xb3\xa2\x88\x6c\x5b\x4e\x90\xc9\x5b\x5b\x9b\x73\x47\xa1\xd1\x3a\x25\xe0\xbe\x21\x54\x75\x10\x3b\xab\x5c\x93\x72\xbb\x64\x63\x79\xa8\xc4\x6e\xba\x49\x06\x2e\x6a\x6e\xe8\xe6\xfb\xa7\x47\xad\x3e\x1c\xba\x9a\x95\xaa\xb6\x43\x09\x1c\xbb\xce\xd8\x80\xbf\x73\x61\x1c\x43\x73\x18\xb1\x21\x52\xdb\x8c\x8b\x98\x77\x5a\x55\x7a\x12\xfb\xcf\x98\x2b\x31\x6a\x5e\x7c\xa7\xc2\xc7\xd7\xff\xf3\x57\xde\x70\xfe\xb9\x65\xbb\x17\x09\xac\x20\x8f\x0a\x62\xc2\xbf\xa8\xd5\xa1\x2d\x4e\x13\x69\x71\x6a\x5b\xd0\x3a\x2c\x73\xda\x7b\x07\x87\x1a\xe0\x03\xed\x14\xc9\x29\xc1\x9d\xb7\x04\x93\xfe\xe3\x73\xcc\xa0\xae\x1e\xe7\xc7\xfe\xa3\x73\xfc\xfa\x11\x6f\x27\x6b\x1c\x2f\x3e\x7a\x96\x8e\x7f\x7a\xe3\xb1\x0e\x16\x9e\x83\x34\x84\xff\xe0\xbf\x05\x5f\x77\x5e\x8e\xfb\x3f\x76\x98\x75\x7b\x41\x6d\x1f\xb5\xe1\x7f\xf3\x18\x02\x60\xd3\xe3\x97\xc7\x0d\xe4\x07\xed\xd7\xf2\xbc\x4a\xe7\x3e\x01\x6d\x97\x10\xf7\x31\x0f\x60\xb6\xd5\x6a\xdd\x94\xd8\xd2\x0d\x5b\xc4\x5a\x86\x8f\xca\x3d\xdf\xd3\x75\x9c\x96\x7a\xbe\x3f\x39\x3d\x36\x32\xcf\xd2\x2f\xf3\x34\x32\x48\x23\xe6\x5c\x79\xb0\x86\x9a\x84\xa0\x85\x69\xdd\xf0\x8a\x89\x6f\xa7\xe8\xa7\x19\x9d\x61\xe1\x55\xa3\x5c\xd5\x4f\xf9\xee\x8c\xdc\x3a\x8b\x80\xdd\x3b\x07\x0d\x41\xe8\x70\x1d\xe4\xb2\x6f\x98\xe2\x1f\x7f\xfa\x97\xc9\x48\x71\x36\x3d\x86\x08\x61\xcd\xa6\x2e\x59\x58\xae\xc5\x5e\x8a\x92\x3a\xd1\xe5\x7a\xa9\x58\xea\x91\x64\xd5\x6d\x81\xd5\xb2\x2d\x74\x92\xe2\xb6\xda\xda\x2f\xd9\x09\x77\xc7\x66\x1a\x07\xbf\x75\xc4\xfc\xb6\x31\x03\xce\x06\x1d\x7b\xa2\x97\x64\x04\x76\xbf\xd9\xf8\xcd\xb7\x17\x45\xbf\xf5\xf4\xa5\xdc\x6f\xf4\xbb\xe6\x53\x8b\xc5\xc1\xef\xc8\xad\x77\x9b\x55\xea\x60\x6b\x08\xa0\x95\x1c\xe5\x2e\xa2\xc1\x32\x6c\x33\x94\x78\xca\xe7\x6d\xb0\xd8\x2d\xd1\x82\x94\xb0\xcb\xdd\x53\x3c\x6d\xd9\x0a\xf6\xdb\x17\x4f\xca\x6b\x4d\x36\xfc\x9f\xa9\xd1\xba\xc2\xac\x93\x9d\xe9\x1a\xef\xd9\xde\x29\xaa\xb2\x1b\x27\x85\x18\x05\x55\xdd\x33\x42\x8f\x67\x37\x74\x3e\xb6\x68\xf6\xd3\x3e\xcf\x3d\xcc\x0c\x67\xf8\x14\x94\x8b\xa7\xe4\xff\x58\x3e\xed\xe2\xfc\x90\x1c\x9d\xae\x3c\x10\x36\x6c\x61\xc3\x86\xe1\x59\xa9\x37\x4f\x91\x81\xc6\xa2\xec\x0a\x99\x18\x14\xd8\xe4\x0a\xe1\x41\x16\x21\x51\xb2\x06\x75\x93\x95\x99\x1b\x56\xc6\x81\xe2\x10\xbe\x05\x10\xb4\xc3\x02\xdf\xb4\x0c\xda\x61\x41\x7b\x3e\x05\xcd\x90\xc0\x3b\x4f\x02\x4f\x60\xd0\x31\x29\x02\x6f\x70\xf0\xb4\x11\x0f\x9e\x92\x2a\x78\xc2\x70\x06\x8f\x26\x41\x4e\xaf\xe5\x82\xfc\x31\x16\xcc\x43\xb3\xe3\xd7\xaf\x1e\x65\xc6\xba\xf8\x25\x87\x2f\xf2\xa8\xe6\xd9\xc4\x1a\x38\x9a\x57\xb8\x07\xfd\x0b\x1c\x5b\xff\x1f\xe2\x68\xa4\xfe\xce\x53\x79\x9a\x23\xa9\xee\xa3\xb9\x9a\xa3\xf7\xa7\x7b\xc7\x87\xff\x47\xf9\x9a\x0f\x65\x3a\x12\xc1\x14\xfe\xff\xbb\xf1\x26\xfd\x9d\x67\xe0\xf3\xfc\xbb\x4d\x8c\xd9\xcd\xd3\x67\x05\xea\x7d\x99\x29\x71\xfc\xe7\x7f\x9b\xf9\xf0\x74\x2e\x97\xec\x4a\x45\x90\xb1\xba\xc6\xbf\xdb\x3c\x7a\x06\xaa\x90\xec\x29\x8d\xce\x18\x2a\xf3\x4d\x0b\x11\x2c\x74\xf4\x4f\x5b\xca\x30\x4f\x63\x78\x3f\xe4\xc5\x97\x6c\x44\x7c\x8d\x42\xe4\xad\x9f\x30\x2b\x97\x9e\x59\xd9\xe5\x51\xb9\xcd\x58\xdb\x17\xcc\x06\x6b\x67\xec\xbf\x0c\x9e\xb4\x59\xee\x51\xd3\x85\x70\x28\x35\x15\xf1\x46\xf9\x7e\x25\x66\xc9\xf2\x29\x13\x5e\x3a\x97\xd3\x53\xfe\xe3\xa7\xcf\xe7\x66\xd2\xe7\x5a\x40\x51\x5f\xb6\x80\x6a\xfd\xc6\x11\x52\x4f\x85\xa1\x0c\xa9\x4f\xe5\x9d\xc6\xbd\xf4\x26\x4c\xf8\x4e\xd9\x28\x6e\xa7\x96\x31\x0f\x0f\x9b\x7d\xe5\x7a\x98\x32\x90\x32\xa6\xc5\xae\x54\x66\x5e\x75\xea\xd8\x8c\xc9\x64\xdc\xac\xc4\xc1\xa2\x91\xb7\xd4\x35\x70\xea\x67\xf0\x25\x25\xbf\x25\x5d\x0f\xa1\x55\x36\x64\x70\xab\xd3\x6c\x26\xd9\x6e\xc6\xf5\x26\x5b\xb9\x9e\x5d\xc9\x81\xc5\x41\xca\xc2\x1a\xb8\xa1\xbd\xa1\x55\x07\x3c\x2b\x14\x9e\xbc\xe4\xa7\x50\x45\xe5\x24\x50\x8a\x55\xd9\xd1\x1d\x07\x89\x51\x97\x6a\xcf\x7a\xca\xc3\x9d\x44\xa8\x3a\x4a\x9a\x67\x3c\x99\x86\x78\x1b\x89\x5a\x1e\x18\xbe\xf2\xe3\xec\xfa\x87\xdc\xce\x43\x64\x26\xff\x48\x19\xd5\xdc\x5e\x64\x97\x2b\x1f\xb4\xef\x1a\x39\xb2\x9d\xe9\xc0\xb2\x30\x57\x2d\xa6\x6e\x42\x13\x60\xff\x79\x2b\x90\x29\x02\xd1\xfe\x0a\x27\x98\xba\x1e\x6f\x0d\xb8\x94\xd4\xae\xc9\x99\x26\x44\x20\x82\x60\x9b\x2e\xa5\xec\x81\xf1\x5a\x7d\x51\x11\x27\x72\x34\x55\x29\x08\x01\x9a\x48\x67\x22\x18\x44\xf8\x18\x73\x58\xf1\xe9\x3c\xac\x2c\xfc\xa1\xdc\x6e\x35\x5a\x00\x11\x0e\x06\xea\x2f\x96\xfa\xfe\x94\x23\x51\x9e\xc8\xb2\x63\xba\xfb\x34\xf6\xb0\xed\x31\xaa\x93\x12\x0e\x0a\xe6\x98\x31\x88\xea\xc4\x79\x57\x1f\xe3\x76\xfa\xfb\x32\xab\xee\xd8\x71\x65\x59\xed\x41\x75\x99\xce\x5c\x14\xa4\xfe\xb0\xfd\x7f\x9f\x9d\x7c\xec\xb1\xee\x47\x3e\xbe\x0b\xa9\x57\xb6\xff\x74\x49\x62\xfc\x44\x56\xf4\xf2\x4f\x11\xb9\x1d\x1c\x03\x4d\x92\x87\x9d\xb1\xed\x76\x70\xa4\x9d\x11\x8d\x58\x54\x3d\x42\x1a\x3f\x83\xf6\x95\xf4\xc0\xa9\x66\x7a\x66\x8d\xd0\x7d\xcc\x8c\x3b\xe8\x26\xb9\xbd\x98\x5d\xc2\xfb\x8d\xd5\x7f\x37\x88\x58\xaa\xad\xf4\x7c\x9e\xb5\xfc\xfa\x6e\x6b\xf9\xec\xd6\x36\x11\xff\xf8\xe3\x93\x84\xa1\xff\x94\xe6\x5c\x17\x77\xdf\xb4\xc7\x69\x01\xf8\xf5\x77\x9e\x61\x49\xb3\x76\xa3\xcb\x3d\x1b\x5d\xe9\xdd\xe8\xd2\x96\x4e\x51\xd9\xdc\xa4\xa4\x0e\x79\x84\xb3\x30\x7f\xc2\x0e\x75\x22\x75\xce\xf5\x16\x75\xf2\xe9\xfc\xc8\x51\xba\xbc\xf4\x61\x9c\xdb\xc0\xc6\xdd\x6c\x5b\x6a\xb1\x6d\x4f\xd0\x95\xb4\x5d\x42\xfd\x2b\xc6\xb6\x21\x4f\xee\xef\x3c\x66\xda\xe3\x70\x47\x4d\xfb\x7a\x89\x71\x71\xef\x09\x54\x18\x61\x08\xd6\xe3\xa5\x77\x0b\xc9\x5a\x39\xcc\x56\xa9\x31\x53\x5b\x4a\x8c\xb6\x57\x23\xd4\x39\xb5\x1d\x95\x91\x7a\xca\x0c\x85\xf5\xf3\x29\x23\xa5\x37\x70\xd0\xe8\x0b\xfd\x49\xf6\x95\xa1\x50\xc2\xe0\x7c\x92\x21\xc4\x63\xb6\x1d\xfc\xb6\x81\xe3\xb0\x51\x2f\xe7\xf3\x69\x9e\x8d\x36\x16\xe5\xc6\xcf\xac\xc2\xff\x56\x0b\xf9\x52\x18\x3e\xcc\x6e\x23\x1f\x6f\xfc\xa6\x8a\xfb\x6d\x23\xaf\x37\x16\xd5\x32\xeb\x05\xf2\xe6\x15\x8a\xff\xdf\x52\xfa\x46\x0d\xb4\x1b\x91\xbe\xb0\x2f\xdb\x75\x18\xa7\x50\x38\x56\xa2\xe9\x10\x45\x69\x28\xe4\xb8\x84\x1c\xb2\xdc\xe3\xa5\x51\x73\x07\xf2\x44\x34\xdd\x48\x97\xef\xc8\xd8\x21\x1a\x60\x9e\x68\xb0\xf9\xfc\x6d\x45\x40\x1e\xc5\x05\x90\x5e\x54\x73\x42\x35\x4d\xbe\xb5\xa6\x84\x65\x33\xa1\x34\x37\x6f\x79\xbd\xc1\x2b\x6b\x66\x76\xd0\x99\x15\x3c\x73\x93\x33\x24\xc9\xa8\x80\xe4\x84\x21\x9c\x04\xab\xce\x70\xbd\xb0\x6c\xd1\x51\x20\x34\xc7\xe4\x9d\x58\xee\x4b\x10\x51\xaf\x91\xed\xe6\x0e\x14\x2e\x33\xa0\x32\x77\xdc\x48\xf6\xc8\x91\x76\xb0\xfb\x75\x27\x3f\xbf\x7c\x02\x99\x1b\x7a\xc8\xdc\xd4\x4b\xe6\x9e\xc9\xbb\x4f\x9b\x34\x50\x5a\xa3\xd8\x4c\xfc\x3a\x12\x78\x26\x8d\x57\x34\x09\x3c\x3b\xfc\x70\xb8\x6f\xb1\xe9\xa9\xa8\x25\x9b\xbe\xbc\xb4\xf0\xf7\xef\x6d\x2e\x37\xce\xc5\x2d\xff\x3e\x83\x7d\xd6\xac\xeb\x3a\x66\xd4\x66\x91\xc5\xe4\x71\xce\xd4\x4b\xa4\xfd\x44\xeb\x49\xfc\x6c\x17\x49\xdb\xd5\xf4\x2b\x6e\xf1\x8f\x76\xcf\x18\x42\xe7\x8f\x8f\x1e\x61\x5d\x95\xee\x62\x47\x3d\xb2\x5d\x1f\x99\x26\xdc\x62\x05\x80\x16\xc5\x9b\x86\x62\x6e\x26\xb6\x39\x80\x0a\x35\xfa\xef\xfe\x4a\xee\x3e\xd2\x86\xb8\x1d\xaf\xb2\xde\xbd\xb8\x8c\x83\x20\x7a\x12\x2f\x5b\x7b\x78\x59\x45\x4a\xbd\x2c\xad\xb7\xe9\x3b\x0d\x4e\x57\x34\x78\xb4\xd1\x3a\x1e\xed\xff\x20\x1b\x66\xf3\x5c\xb4\x5f\x3f\xc7\x86\xb6\xe1\x9f\x6f\x91\x10\x42\x12\x12\xc4\xca\xd9\x5e\xd5\x74\x1a\x49\xf5\xfe\x9e\xf6\x11\x4f\x58\x6f\x4c\x2e\x4e\xa9\xff\x19\x29\x01\xf5\x29\x25\xc9\x04\xf2\x5b\xf4\x46\x4b\xd8\xb6\x86\x24\x1c\x19\xe4\x3d\x04\x03\x3c\x2f\x65\x73\xce\x25\xd6\x54\xce\xce\xcc\x47\x9f\xca\x1c\x35\x40\xe0\x89\x14\x49\x2b\xf2\x83\x3c\x50\x46\x07\x76\xc6\x69\x52\x6e\x2b\xdc\x82\x7b\x72\x15\x1f\x97\x02\xcd\x1b\xd3\x55\xc3\x88\x80\x6b\xff\x35\x2f\x46\xe5\x57\x9c\x2d\xda\xe7\xfd\xd6\x96\x27\x90\x81\xe9\x36\xb3\x87\x07\x84\x56\xcd\xd0\x95\xfc\x4d\xb6\x4f\xb0\x92\x4d\xe7\xa7\xd8\xfa\xb4\x18\x4e\xca\x0a\xf7\x4b\xda\x03\xf9\xf5\x64\x3c\xc6\x0b\xe1\x32\x41\xb0\x78\x98\x2e\x14\x9d\xaa\x37\x19\x2b\x7d\x2c\x50\xc7\xed\x2d\xc2\x1d\xdc\x13\xaa\xd0\xc9\xb1\x91\x9f\x9d\x9b\x93\x17\x6e\x15\xcb\xdd\x9d\x18\xc5\x6d\x67\x74\xf2\x81\xcd\x5b\xf6\xd3\x54\xc1\x21\xca\x11\x1a\x4c\xe5\xf8\x61\x36\xf2\xca\xa2\xc6\x21\x98\xca\x21\x08\x49\x00\x50\x19\x0b\x10\x21\x03\x64\x59\x8c\xed\x0a\x55\x9d\x36\xd3\x4d\xed\x74\xf0\x06\xa3\x61\x47\xc2\xab\xaa\xee\x38\x99\x43\x75\xa7\x9e\xea\x4e\x92\xf1\xf6\x10\xb6\x21\x3d\xd9\x9c\xe9\x35\x18\x49\x6f\x00\xd5\x82\x3d\xed\x8d\x54\xa5\x4b\x84\xb8\x62\xa0\xd3\x51\x6f\x58\x4e\xa7\xe9\xbc\xce\x46\xee\xfc\xb8\xdd\x9d\xc4\x63\x9a\x23\xb7\xbb\xe3\x78\xd2\x76\xd2\xa6\x59\x21\xcf\x5c\x77\x2b\xe2\xcc\xe9\x60\x09\xbb\xd7\x18\x5a\x39\xb2\x31\x0c\xa1\x9c\xdd\x10\xa7\x08\x15\x8e\x0b\x23\x8a\xe5\xcb\x5b\x2b\x16\x1e\xc8\xc5\x1a\x45\x44\xb1\xf3\x05\xc5\xe2\xe2\xe8\x58\x33\x18\xcc\x9d\x11\x0c\x27\x69\x05\x04\x81\xcc\x6c\xd7\x2e\xa7\x5c\x7d\x88\xbd\x66\x7f\x56\xbd\x90\x1f\x62\x83\xc3\xa8\xe5\x37\x0e\x56\x85\x67\xb9\xa8\x8b\x4a\xef\x4a\x42\x9c\xae\x8b\x69\x18\x5d\x1a\x6a\x70\x9c\x2e\x26\xbd\x59\x8e\x9a\xb4\xb2\x95\x78\x74\xeb\xee\xc1\x3c\xb6\xbe\xa0\xbe\xe2\xf5\x59\x00\x6d\x86\xa9\x3b\xda\xda\xca\xdf\x6a\x18\xab\x72\x00\x54\x02\x3d\x98\x4a\x33\x1d\xf4\xae\x96\xe3\xba\x1a\xb2\xe7\x45\xf8\xb0\xde\xda\x5a\x72\xf2\x79\xd7\x1c\x9b\x9b\x39\x56\x93\x9d\x13\x2c\x80\x52\x4e\xdc\x42\xa2\x99\xee\x4d\xa7\x94\xbc\x86\x46\x42\x05\x60\x28\xd1\x2b\x28\xe7\x30\xc7\x64\x5c\xbb\x70\xc9\x19\x2c\x55\x06\x30\xc0\x73\x35\x65\x9b\x71\xc2\xc9\x03\x05\x06\x12\x2c\x8e\xee\x30\xbe\x65\xc3\x25\xf6\xaa\x6b\xeb\x23\x59\x44\x79\x27\xfb\xbe\xac\xf6\xd5\x80\xf2\x52\x33\x1c\x23\x24\xb1\x2e\x29\xf7\x86\x78\x47\x58\xb2\x61\xd1\x12\xb6\xc8\xe2\x73\x8d\x0a\x95\x5b\x5b\x81\x9e\xf1\x68\x73\xa6\xba\x68\x6b\x6b\x33\x0c\xec\xc1\xc5\x48\x1e\x73\x5c\xcd\xf7\xb8\x09\x53\x81\x75\x3c\x87\x31\x2b\xd1\xe1\x90\x09\x48\xe3\xda\x06\x7c\x18\x4b\xa1\xbf\xaf\x49\xf1\x8f\x24\x51\xe8\x6e\x50\xdc\xff\xe9\x95\xe8\x6e\x0f\x44\x7f\x4f\x3b\xe1\x33\x4c\x56\xbb\xa4\xf1\x5e\x18\x7f\xaf\xc9\x95\x2d\x7c\x70\x54\xf4\xb4\x48\xbf\xc9\x84\xd7\x4f\xb1\xa6\x5a\x3a\xfe\x45\x56\x83\x14\xe6\x8c\x51\xd5\xfb\x23\x60\xf4\x2c\x17\xc3\xf2\xf0\x84\xb4\x1e\xa2\x9e\xb5\x18\x61\x61\x7e\x4b\x76\xfe\x80\x31\x90\x94\x16\x2a\x1d\x49\x53\xb2\xe5\xfc\xc7\x67\x33\x02\xd3\x27\xf8\x19\x0d\x9a\x37\x82\xed\xca\x67\x2b\x12\xa1\x35\xc8\x76\xbe\x1d\xfc\xfc\x12\x93\xa1\x65\xc8\x5a\x2b\x04\x16\x4c\x68\x78\xce\x06\x3e\x7b\x47\x7f\x0d\x94\x25\xc9\xf6\x62\x50\xe8\x6f\x4d\x23\x80\xb7\x6c\xf5\x68\x21\x4a\x9f\x02\x64\x5b\x2b\xa4\x4b\xa1\x1d\x11\xc7\xd6\x69\xa6\xe6\xcf\xd0\x2d\x5d\x39\x17\xfe\x4b\x5e\x72\x7f\x50\x87\xf2\xa9\x3a\x92\xce\xd4\x8f\xdf\xbc\x7e\x8a\xfe\x23\x2d\xd6\x67\xd8\xde\xfe\xff\xf3\x12\xce\x1c\xda\xe7\x7e\x7a\x31\x6e\x5f\xb8\x4d\x5a\xb2\xcd\xd6\x05\x9c\xb6\x6c\x22\x5f\x1a\x4f\xb9\x7f\x3b\x37\x98\x0f\xea\x70\x7f\x7e\xf8\xdf\xe7\x7b\xa7\x87\x7b\xff\xe2\x5b\x38\x05\x50\xe6\x9e\xcb\xd5\x19\x15\xd6\x97\xf1\x52\x2e\x5c\x81\x19\xc2\xe6\x86\x68\x5d\xc7\x5c\xc5\xcf\x49\x1f\x6f\x79\xb2\x8b\x1d\xf4\x80\x4b\x92\x1f\x56\x7f\x4b\x12\x5a\xa6\x64\x35\x61\x5d\x86\xd9\x27\x62\xf7\x26\x90\xe5\x12\x90\x41\x68\xdd\x88\x45\x6b\xae\xf7\xe6\x1d\xf2\x09\x5d\xf5\x4e\x93\x6d\xdf\x95\x9f\x2b\xb8\x58\x2f\xe3\xd0\x62\x8d\xf6\xc5\xdf\x63\xe2\x81\x96\xe2\x9e\xdd\x21\xda\x34\xcc\xf8\xa7\x6f\x5d\x7e\xf9\x2f\xa2\x72\xfb\x22\xaa\x22\xf0\xc4\x3f\x74\x13\xb5\xf6\xf4\x3e\xfd\xe3\xc7\xf4\x7f\xd7\xab\x94\xf5\xf7\x26\x5e\xa9\xfc\x33\x1c\xbd\x4b\x72\x59\x65\x72\x86\xe4\xff\xc8\xce\xe1\x48\x5b\xa7\x72\x22\xb7\xd0\xb2\x0c\x25\x92\x64\xd2\x4a\xfe\x38\x3b\x83\x68\x61\xef\x15\x62\x2d\x12\xc3\x7b\x53\x6e\x5c\x0b\x38\x88\xd6\x0e\x85\x40\xef\xed\xef\x10\x94\x5c\x0b\x63\x6a\x94\xb2\xc1\x0c\xf6\x7e\x99\xf7\xc6\xd3\x65\x3d\xa1\x2f\x32\x39\xb3\x6b\x86\x69\xc5\xab\xcf\x69\x72\x31\x14\xcb\x4b\xe0\x93\x2c\x7f\x6d\xb0\x29\x33\xad\x42\x26\xd5\x6a\xcc\xaf\x55\x3a\x9f\x3b\x46\xbf\x5a\x14\x32\x5d\xad\xd4\x31\x17\xe5\xf1\x15\x72\xb8\xad\x7a\xc6\x9b\x7d\x71\xed\x54\x64\x0d\x46\xb5\xa7\x9d\x03\x6f\xdb\x77\x44\xb9\xbb\x08\xd5\xd7\xf1\xbc\x27\xd1\x7c\x21\x4b\x65\x69\x43\x31\x2b\x0f\x43\xdd\x3d\x59\x9b\x73\xcc\x1e\xd3\xb8\xff\xc3\x8f\xa2\x35\x76\x71\xff\x35\xcf\xb5\xe7\xb8\x05\xd4\x1d\x38\x72\x77\x1a\xb5\x95\x2c\xe0\xc0\xff\x19\x3b\x7d\x3f\xad\x49\x58\xd4\x75\x0d\x86\xbd\x7e\xa2\x9a\xdc\xf8\x67\xeb\x35\xad\x1c\x34\x8b\xe8\xfe\xa8\x67\xdb\x79\x48\xcb\x15\x5e\x7a\x18\xae\xc1\x26\xce\x23\x21\x93\x7e\x9a\x2e\x6f\xf2\xe2\x97\xe5\xb5\x4c\x6c\x05\x92\xdb\xa1\x70\xd9\x99\x54\x21\x27\xfe\x42\x54\x2e\xfc\xd4\x99\x90\x7d\xd3\x1c\x3c\xa5\xcc\xfa\x1d\xed\xc7\xe1\xfd\x59\x3e\x9b\x4f\x33\x2b\x26\xfe\x20\x0e\xd1\x69\xc6\x87\x2c\xbd\x75\xc2\x87\x82\xc9\xa7\x1d\x96\x8a\xe3\xf2\x3a\x9f\x66\x67\xe9\x18\x68\x09\xc1\xd3\xd8\xd1\x63\xc1\xe7\x38\x3b\xec\xa3\x78\x97\xc1\x44\xcb\x48\x01\xc7\x8e\x28\x57\x58\xf1\x06\xec\xa3\xac\xf9\x9f\xb1\x37\xf3\xa1\xeb\x11\x09\x2f\xbe\xbb\x3e\x60\x3e\xd0\x49\x7d\xdc\x9d\x1a\x09\xb9\x5c\xa6\x61\x85\xc9\xe8\x8b\x9e\xe5\x1d\x34\x9c\x74\x7f\xed\x96\x03\x47\xf5\x7b\x09\x87\x77\xc7\xa8\x6e\x57\x0a\x6a\xed\x1b\x21\x39\x5c\x4b\x20\x87\xaf\x0a\x5d\x6c\x5f\x81\x75\x9d\x1a\x4c\xac\x33\x06\x6c\xfb\x1c\x32\x64\x5b\xc4\x18\x6f\xf8\x9a\x91\x52\x1c\x21\x6a\xc1\x2b\x41\x6a\x45\xd4\x73\xd6\xbe\x23\x2b\x66\x85\x00\x4f\x3c\xce\x6f\x50\x64\xf0\xb4\x84\x7f\xa7\x49\x84\x2b\xb5\xd9\x5a\x37\x30\x34\xc0\x6a\xf8\x85\xa2\x94\x6a\x41\x48\x44\x4d\x7b\x27\xf8\xd2\x4e\xa7\x88\xd3\x19\xe2\x6b\x64\x37\x77\xe1\x0c\xd3\x9c\xc2\x19\x83\x4e\x85\xaa\x9b\x59\x78\x42\x50\x9d\x2a\x2a\x9c\x1a\x91\xc2\xae\x52\x80\x74\x93\xc4\x7b\xde\x60\x1a\xe5\x66\xd3\xac\x73\xce\xad\xec\xa9\x66\x1a\xfb\xc0\x15\x1e\xf2\xb6\x26\x37\x30\xff\xbc\x36\x7b\x59\x6b\xf9\x98\xfd\x0c\x56\x4e\x56\x2c\xdc\x1a\x5a\x08\x2f\xcc\xc0\x35\x49\x86\x61\xf8\xbd\x0b\xd6\x70\xfe\x1d\x32\x1d\x79\x02\x40\x36\xb1\x35\x01\xcc\x49\x60\xdd\x02\x6f\x00\xbe\x74\x1d\x55\x46\x9e\xa3\xca\xed\x93\x65\x1e\x33\x5b\xe6\xc1\x3d\xd1\x9c\x30\x06\x10\xc6\x27\x19\xb9\x73\xa3\xde\x29\xcc\xae\x2b\x37\xfc\x3d\x5b\x86\x5d\x37\x9c\x96\x92\x12\xed\xe1\x5a\x4f\xa6\xdf\x1a\xb1\x4a\x21\xfb\x6b\x23\x5c\x6a\x29\xee\xbb\xc1\x52\xcf\x23\x12\xa7\x6e\xf8\x99\xba\x2b\x3d\x73\xc3\xf5\xc9\x29\x12\xc7\xed\x18\xbb\xe1\x27\xde\xe3\xe0\xb9\x1d\x6a\xef\x56\xb8\x82\xad\xb8\x23\x65\x8e\x09\xe1\x9f\x9c\x70\x7b\x3b\xc2\xf6\x1f\x78\xb4\x3c\xbf\x58\x61\x3e\x3a\x00\x49\x3e\x72\x92\xd6\x16\x01\x51\x7b\x2a\xaa\xba\xcd\xaa\xd6\xb2\xf8\x20\x63\x9b\x5b\x17\x44\xfd\x5d\x46\xfd\xf5\xcf\xbe\x29\xfd\x99\x63\xe5\xe1\x15\x36\xf9\x4f\xe9\x8d\xed\x77\xd2\x62\x75\xa4\x09\x6a\x9c\xaf\x98\xe7\xe9\x58\xdc\xf1\x0f\x24\x7c\x68\x2f\xed\xf8\x35\x71\x45\xde\x85\x1d\xbf\x26\xe6\xa8\x6b\x59\xc7\xaf\x29\x4f\xff\xa2\x8e\x5f\x13\x13\xb5\x4e\xa6\xe9\x5f\xd0\xf1\x8f\x94\xeb\xda\xe5\x1c\xff\xf8\xe6\x9f\x3a\x77\x3c\x43\x7e\x23\x57\x61\xfc\xe6\x87\xb5\x52\x1d\x67\x71\xc6\x6f\x7e\x14\x5d\xab\xd0\x76\xb0\x6b\xd6\x60\xfc\xc6\x29\x14\x17\x73\xdc\xdf\xd9\x71\xc2\x68\x55\x42\x68\xdf\x0e\x95\x8b\x12\x82\x5f\xd9\xc1\x72\x4d\x42\xf0\x77\xa2\x73\xe1\x41\xec\x0f\xcd\x58\x5a\xb0\x10\x61\x35\xaa\x83\x94\x41\xa2\x1f\x9b\x89\xa4\x41\xcb\xce\x9b\xf5\x27\x3c\x77\x35\x43\x94\x29\xcd\x2c\x66\x08\xfe\xc9\x0a\x76\xd7\x72\xdc\x7f\x65\x3a\xc7\xa3\x7b\xe7\x5d\xc9\x71\xff\x3b\x4a\xe1\x5d\x74\x70\x12\xa0\x1e\x6c\xaf\x72\x88\xf9\x4e\x74\x2d\x72\x88\xe4\x3c\x5b\x6b\x1c\x62\xa8\x77\xbb\x16\x31\x1c\x28\x7e\xa0\x03\xc5\x63\x16\x3d\xde\x03\x05\x5d\x02\x8d\xa7\x65\x59\x85\x30\x4f\xfe\x6b\x11\xbd\x84\x1f\x8f\x12\x18\xa1\x0f\x92\x46\xd5\xc3\xc3\x4e\xb4\x5d\xd8\x7c\x80\x0b\xc8\x96\xb6\xb7\x2f\x1c\xce\xbd\x22\x9d\xde\xd5\x79\x53\xda\xa7\xc8\xa7\x2d\xdd\x93\xd6\xa7\x72\xaf\x97\xe7\x34\x1c\xb5\x8f\xe5\x57\x36\x36\xbd\x4a\xa7\xd3\x63\xb6\x7e\xc3\x59\x51\xc7\x17\x97\x82\xc5\xea\x67\x0b\x44\xff\xba\xd8\xb9\x44\x10\xfc\xbf\x93\x36\x11\x9e\x27\xf9\x9e\xd2\x3a\x0f\x4d\x7b\x3a\x9e\x60\x36\xd4\x74\x51\x3c\x30\x67\x0e\xec\x96\x34\xb2\x43\x09\x49\xb3\x54\x29\x26\x4b\x76\xc4\xb2\x97\x15\x88\xd6\x28\x63\xd1\xf5\x32\x83\x8c\x5a\x25\xb6\xd2\xf4\x09\xdc\xff\x43\x5a\x2f\x9c\xa6\x78\x4e\xcd\xad\x92\x57\x62\x5e\xe5\x70\x1c\xfb\x36\x84\x53\x3b\x70\xe8\xee\x3d\x45\xb2\x78\x78\x68\x7f\x63\xeb\xbd\xeb\x0f\xcf\x18\xca\x96\x6c\x34\x81\xaa\x94\xd3\xac\x47\x18\xb6\x61\xd6\x9b\xa5\xf3\xb0\xed\x7d\xed\x3e\xd0\x33\x6f\x63\x88\xf4\x70\xa3\x20\xba\x63\x79\x73\xc4\x73\x96\x08\xce\xcb\x45\x3a\xdd\xc8\x0b\x59\xd0\x06\xe2\xd7\x6e\x84\xb3\x3a\x0a\x62\x98\x7f\x3d\x1d\x11\x89\x40\xd7\x66\x83\x86\xb0\x99\x34\xfb\xe6\x4b\x2a\x5d\x46\x37\xd2\x72\x28\x24\x3c\x36\x39\xc1\x04\xd2\xde\xd8\x7c\xd9\xbe\xc4\xba\xa3\x1a\x02\xda\x4f\x9a\x4c\x3b\x3e\xe3\x12\xcc\x37\x8a\xa2\xd4\xb1\x0c\x82\xb3\x73\x24\xc7\xe7\xa8\xf8\x83\xe3\xa3\x3f\xfc\x03\xe3\x43\xce\x0b\x36\xde\x6e\x0c\x0d\x85\x68\x0d\xce\x51\xd7\xb0\xe0\x6b\x47\x9b\x84\xaa\xc0\xb4\xbc\x09\xe5\xf0\x32\x34\xb1\xa0\x3a\x53\xc8\x39\x04\x40\x65\x7a\x8b\xf2\x7d\xfe\x2d\x1b\x85\xaf\xa2\xed\x60\x63\x06\x8b\x9e\xe6\xba\xdd\x5c\xd9\xb2\xe3\x74\xee\x51\xb0\xea\xe8\x04\x81\x4a\x83\xfa\x8e\xeb\x9f\xe9\x80\x5f\x61\xd5\xa1\xbe\xa7\x69\x3d\xb7\xdd\xdb\x74\x39\x9a\xfc\xcd\x53\x86\x52\xb8\x63\x45\xca\xec\xfe\xb6\x13\xe2\xe6\x3f\xd9\xb1\x54\x39\xa0\xc1\xcf\x9d\x64\xb8\xbd\x3f\x7d\x7a\xf1\x87\xf7\x2b\xdd\xff\x17\x65\xef\xe8\xe0\x6a\xef\xfc\xfc\xf4\xe8\xdd\xe7\xf3\xc3\xab\x8f\x7b\xc7\x87\x97\x09\xac\xec\x91\xc8\xc8\x44\x21\x51\xfe\x52\x7a\x69\x75\x53\x27\x0d\xf3\x81\x05\x85\xa2\xa4\xf9\x9f\xef\x81\xab\x0a\xb6\xe9\x6a\xf4\x6b\x95\x7b\xdc\x71\x29\x71\x7b\xbb\x33\x2e\x3a\x49\xfa\x8b\xfe\x65\xef\x2b\xe6\x56\x0f\x72\x34\x94\xc1\x7f\x0f\x0f\xb0\xc9\xe0\x43\x6f\xbe\xac\x27\xe1\x3d\xb6\x2d\xce\x18\x9d\xbb\x10\xd8\x98\xb8\xc2\xb9\x22\x37\x8c\xd6\xbd\x80\xba\xc1\xb0\x64\xb4\x0a\xd7\x30\x81\x9c\x4b\xd8\x46\xd2\x04\xb2\x59\xda\x15\x19\xa4\x6f\xcb\x41\xb9\xbd\x1d\x55\x5c\xaa\x8e\x47\x2f\x94\x8c\xfb\x27\xe6\x62\x4c\xa6\x22\x12\x8b\xf5\x63\xf6\x15\xd9\x0a\xc3\x20\xb0\x03\x9f\xc0\x23\xe0\xa5\xa8\xa8\x73\x97\x91\x0d\xd5\x84\x32\x46\x5f\x18\x85\xf5\x22\xc5\x8c\x88\xd4\x85\x4b\xa5\xc6\x27\xee\x36\x7c\xb2\xae\xc1\xe8\x7d\xa1\x46\x31\x46\x20\xe6\x71\x32\x0c\xf1\x48\x5e\xf4\xd2\xf9\x7c\x7a\xc7\x37\x11\x95\x6f\x9b\x5d\x3f\x4c\x3a\x57\xcc\xef\xc5\x58\xcc\xb9\x2f\xf8\x36\x77\x06\x9c\xd2\x51\xb1\x28\xf1\x7e\x45\xf5\x83\x97\x9b\x46\x03\x1b\xba\xce\xee\xaa\xd6\x52\x66\xdf\x99\x33\x4f\xb3\x09\xeb\x4d\x1e\x1d\x84\xd5\x45\xff\x12\x75\xc2\xec\xb9\x19\x4e\x60\x2a\x2c\x05\xfa\xab\x63\x9d\xf5\x27\x98\x97\x63\xde\xe4\xe1\x0e\xef\x61\x0f\xd3\xe1\xc4\xbf\x2a\x95\xa3\xcc\xde\xb8\x2a\x67\xc4\x52\xe2\x35\x8f\x79\xb3\x63\x14\x86\x05\x2e\xd0\xd2\xa4\x95\xcf\x26\xd4\x4e\x67\xae\x99\x39\xad\x79\x77\x63\xad\x6f\x66\xa4\x5b\x60\xf2\xe7\xf7\x04\x3b\xe6\xc2\x89\xbd\xa4\x51\xb7\xfb\x69\xa1\xf1\x0f\x84\x24\x22\x4b\x04\x3d\x88\xe2\x46\x3a\xec\x17\xea\x52\xbe\xc7\xd4\x57\x13\xbd\x1a\x4e\x7a\x19\x5f\x71\x55\xa2\x6f\x3c\x6b\xcf\x11\x52\xb3\xd3\xd5\x11\x56\x1b\x66\x48\x03\xec\x09\x42\xb3\xad\xad\x16\xc2\x93\x0c\xee\xf6\x5f\xb4\x69\x2d\xae\xc6\x74\xfa\x63\x2e\x8e\x9b\x99\xb0\x41\x55\xb3\xba\x7a\xc2\xc4\x2d\x45\x88\xdb\x64\x4d\x75\xf1\x3b\x31\xf3\x66\x27\x6e\x90\x7a\x1a\xfe\x5a\xdc\x3d\x97\x9a\x62\x83\x6f\x77\xf3\xf0\x8e\x37\xd5\x5a\x8c\x60\x54\xe2\xd9\xd6\xd6\x0d\x13\x99\x9d\x6e\x82\xa0\x56\xde\x6d\x84\x9f\x73\xf5\xe1\xf3\x25\x23\xb5\xa2\xd5\x87\xb4\x1a\xbb\x4a\x20\xb3\x72\x1e\x46\x83\x9b\x8b\x1b\x53\xf4\x76\xb2\x14\xf8\xa5\x26\x63\xf8\xf1\x8b\xab\x88\x02\x35\x39\xa3\x1c\xa5\x1d\x49\x2b\x5c\xcd\x9e\x3b\x1b\x10\xb8\xbe\x18\x5d\x1a\xdf\x3b\xea\x32\x97\x3d\xb3\x0a\x82\xed\x8e\xbd\x23\x7a\x45\x71\xbb\x6b\xe2\x4c\x3e\x71\xf0\x33\x0e\x1f\x6a\xe2\xa0\xaf\xe0\x36\x98\xbb\x07\xce\xab\xf3\xe0\x05\x07\xe1\xb5\x67\x5d\x07\x45\xa2\x71\xea\x8a\x5f\xed\x90\x42\x49\xdf\x83\x0e\xe0\x9e\x2b\x35\xf2\x3d\xec\x67\x1e\xd8\x13\x65\xf8\x89\x48\x91\xd9\x76\x52\x19\xfa\x6d\xac\xf8\x5c\x1d\x69\x93\x21\xec\x92\x9d\x39\xa2\x4e\x19\xe6\xa9\x41\x1c\x73\xb9\x81\x47\xea\x01\xad\x4f\x7c\x24\x34\x93\xdb\x5c\x3e\x8a\x2b\x41\x9b\xfa\xf4\x82\xd7\xdd\x25\xba\x65\x63\xf0\x36\xdc\xdd\x99\x63\x81\x2d\x3e\xf2\x54\xb5\x74\xaa\x2a\x94\xfd\xce\xa0\x32\x95\xd5\x26\x39\x39\x79\x15\x87\x1d\x7f\x49\xde\xa5\xac\x99\x99\x5b\xe7\x22\x6d\x9a\x89\xbe\xa4\x37\xca\x28\x4b\x72\x77\xfa\xa5\x97\xca\x01\x95\x28\xf0\x74\x5e\xd0\xe1\xfc\xde\xe1\x74\x81\x41\x31\x3b\xf6\x8e\x30\x5b\xf9\x8e\xda\xbc\x77\x78\xef\x86\x3d\x59\xe4\x72\x75\x41\xce\x68\x84\x00\xd9\xc9\x80\xed\xc4\x8a\x8a\xec\x1a\x5b\x49\x75\x18\xa6\xb6\x13\x44\x76\xb3\xac\x0f\x74\x18\x7e\x60\x27\xc0\x0f\x98\x4c\x58\xa9\x29\x00\x53\xea\x98\x48\x2a\xa3\x5e\xf0\xa8\x67\xec\xb3\xdc\xad\xcb\x5b\xc4\x2b\x94\x8c\x4c\x61\xbb\x4c\xa8\xd9\xab\xb2\xab\xce\xa6\x8f\x16\xfa\xfb\x17\xd6\x39\x11\x98\x96\xba\xa5\xd9\xac\x11\x7e\x60\xb4\x71\x30\x61\xc8\x73\x33\xe4\xb9\x1a\x72\x42\xa9\xbd\xc8\x11\x42\x95\x06\x3d\xb5\x06\x3d\xb5\x07\x3d\x23\x68\xd1\x3a\x44\x97\xc6\x2a\xef\x39\xe3\x9b\x4a\xed\xf9\xf2\x62\x7e\xc9\x99\x8e\x93\xd4\x9d\x11\xf3\xcb\x41\x91\x8c\xd9\x67\x00\x30\xc7\x6f\x37\x82\xed\xb1\x9e\x23\x15\x2c\x8f\xa4\x22\x58\xd1\xc6\x1c\x29\x98\x89\xb5\x66\x82\x55\x25\xc8\x14\xaa\x84\xdf\xd1\x01\x69\x3b\x71\xe3\xd8\x2b\x2c\x8d\x88\x49\x28\xc7\xca\x8a\x91\xe6\x5c\x13\x35\x58\x04\x2e\x5b\x45\x3a\x5b\x1a\xa7\x09\x8f\x13\x06\xea\x71\x9a\xac\x1d\x27\xfc\xf4\x05\x9f\xdc\x60\x74\x26\x8e\x6a\xb5\x61\x8e\x84\xeb\x51\x7b\xa1\x28\x03\x0c\x19\x0d\x86\x35\xc6\x62\xe1\x5b\x81\x39\xd7\xd6\xb2\xb4\xde\xec\xc3\x80\xa2\x8f\xe1\xc2\xf6\x31\x0c\x23\x84\xb6\x0d\x05\x2e\xcd\x1c\x39\x9b\x13\x74\xed\x10\xdd\x97\x68\xa8\x77\x5d\x65\xe9\x97\xd5\x26\xc2\x73\xaa\x7e\xc9\x2f\xdf\xee\x20\x6b\x04\x0f\x64\xf2\xa6\xc9\x8a\xa5\x9f\xdc\x54\x08\x19\x26\xfd\xde\x2b\x92\x81\xb5\x19\x51\xf4\x7e\xb4\x80\xba\x2a\xac\x1f\x71\xf4\xf1\xec\xf0\xf4\xfc\xea\x78\xef\xf4\x2f\x9f\x3f\xb5\x62\x8f\x4f\xfe\x7a\x78\x75\xf8\xdf\x47\x67\xe7\x47\x1f\xff\x8c\x18\x97\xb7\x59\x20\x4e\x0f\x29\xf8\xe3\xc9\xc1\x21\xba\xcb\xe1\x40\xd4\x54\xbb\xda\x3f\xf9\x78\x7e\xf8\xf1\x9c\xb3\xb1\x58\x3e\x85\xe0\xe4\xc3\x97\xda\x48\x15\x6e\xed\x3a\x74\x29\x3b\x55\x17\xb6\xd4\x06\x21\xbf\xd5\x1d\xc0\x52\x8d\x96\x3d\x0d\x24\x4a\x3a\x96\x65\x90\x38\x8f\x54\x2c\x2e\x85\x47\x0c\x11\xa7\xc2\x39\x3c\xc7\xb9\xb0\x8f\xa8\x70\x08\x1c\xb4\xf0\xa0\x5a\x0a\x24\xb4\x97\x3e\x86\x90\xd2\xb4\xda\x56\x1e\x2b\x1b\x0a\xd4\xb6\xcf\x4a\xad\x5c\xd4\x9c\x36\x6d\x7b\xed\x7b\x58\x0c\xe8\x26\xa1\xca\xc6\xec\x1a\xa7\x4e\x9a\x47\x67\xf6\x64\xcd\x78\x34\x74\xa0\x67\x1d\x11\xf8\x10\x78\x42\xa9\xfe\x34\xd6\xfe\xc9\x89\xec\x68\x4f\xd2\xc6\x5b\xb9\xd1\x2b\x49\x4a\x84\x2d\xd3\x5c\x3a\xcc\xe1\xbc\xb6\xa5\xfb\xe4\xae\x41\xdd\x6a\x2b\x8d\x61\x9f\x7e\x5d\x89\x0a\x50\x2b\x89\xc3\x2b\x41\x77\x8d\x86\x1d\x50\x88\x69\x82\x26\xa7\x1b\xd2\xd2\x28\x1b\x33\x50\x2f\x3d\xc2\x57\x56\x1c\xb4\x85\xe3\x50\xbb\x11\xdf\x68\xd1\x97\xec\x69\xa0\xe5\x66\xa0\x8c\xb6\xb6\xda\x18\xe2\x18\x1a\x2e\xe1\x44\x9e\x64\x78\x2c\x5f\xb1\x82\x53\xf3\x28\xff\xe2\x15\xd6\x10\xbd\x9a\xcf\xa3\xa5\x56\xcb\x4c\x0a\xcd\xc6\xce\xdf\xf6\x0d\x89\x19\x27\xac\x92\x39\xc7\x1b\xe7\x9d\xc1\xfc\xed\x64\x30\x01\x0a\x33\xbe\x98\x5c\x9a\x9c\x2f\x26\xdb\xaf\x2e\x07\x56\x66\x63\xf2\x18\x40\xc8\xc8\x92\x01\x24\x75\x1e\x09\xbd\xe0\x86\x9a\x86\x8e\x22\x9f\x99\x08\x36\x48\xb5\x6b\x44\xed\xb2\x74\x88\xd0\x74\x65\x28\xa6\xb8\x51\xab\xed\x45\x3f\x01\x1f\x2d\x1a\xd8\x4c\x49\xfb\xcc\xda\x18\x66\xd6\x35\x63\x3d\x24\x4b\xc6\x27\xa7\x5d\x46\x39\xa2\xb1\xd5\x1e\xba\xd1\xa1\x65\x4b\x8d\x48\xdc\x8d\x81\x95\x51\x65\x05\x99\x75\x23\xa2\x2f\x16\x34\xf2\x8a\xc1\x16\x96\x7f\x65\x0b\x89\x5f\x17\xb2\x6e\xea\x55\x30\xf5\x4a\xde\x35\x24\xee\xfd\x30\xe1\x32\xa6\x09\x97\x32\x4f\x54\x39\xce\x94\xe4\x49\xb7\x29\x27\x24\xf4\xec\x94\x9f\x20\xbd\xee\xc5\x48\x58\xa9\x20\x4f\x48\x35\x4c\xd4\xcc\xb4\x10\xca\x3d\x53\xb3\xf2\x4e\xcd\x8a\xa7\x66\x75\x49\x7e\x31\x78\x6a\x8e\xd7\x4c\xcd\xb1\x7f\x6a\x8e\xed\xa9\x39\x91\x53\x73\x8c\x8a\x0e\x3b\x83\xf1\xdb\xd1\x60\x04\x53\x73\x82\xe7\x21\x33\x35\x47\x8d\xa9\x39\x69\x4c\x1f\x1e\x1d\x9c\x43\x73\x7b\x38\x78\xf2\xb8\x3e\xa6\x3d\xb3\x67\x33\xdc\x84\x93\xfa\x26\x7c\xe8\x52\x10\xdb\x63\x77\x0b\xcd\x61\x9d\x1e\xfe\xd3\x7c\x01\x37\x15\x46\xfb\x8f\x01\x6f\x34\x61\x1c\xee\xf4\x48\x4b\x45\x67\x1d\x60\x0e\x7d\x84\x0a\x20\xcf\xfc\xc1\x06\xc1\x04\x6d\x2c\x26\xfa\xc6\x63\x46\x70\x8f\x1b\xb0\x42\x7f\x0b\xb6\x17\xdb\x01\xa2\x9c\xca\xc4\x81\xd7\xbc\x94\xe8\x81\xc7\x1b\x36\x9b\x63\xda\x26\xfa\x1b\x3b\xda\xfc\xd2\xe3\xc3\xba\xd8\x2d\x5c\x9f\xd5\x85\x74\x54\xcd\x9f\xc6\xfc\x63\x1f\x89\x5a\x8d\xd4\x66\xe6\x5b\x5b\x58\x41\xf5\x69\x8b\xab\x5e\xa0\xf9\x47\x59\x65\xa8\xb6\xcd\x72\x0a\x05\x9e\x4e\x4b\x0d\xbd\xa1\xb5\x52\xa0\x8a\xe7\x32\xfc\x13\x9e\xef\x36\x68\xd6\x91\xff\x02\x05\x1d\x51\xc2\xba\x59\xa0\xb8\x0f\x1e\xd8\x55\xf1\xc6\x24\xbd\x45\x74\x87\x65\x91\xff\xbe\xcc\x36\xd0\xb5\x67\x40\x70\x10\xbd\x3f\x91\x83\x0e\x76\x96\xee\xd8\xea\xe1\xf0\xee\x2b\x4f\x59\x5b\x5b\xcb\x30\x20\x69\xdd\x06\xbb\x04\xab\x9d\x8c\x8b\xb2\x78\x51\xc0\x5a\x80\x79\xb0\x81\x6c\xe7\x46\x5d\x42\x25\x60\x00\x11\xac\x36\xaf\xa1\xa4\xac\xc6\x8b\xe0\x51\x2f\x68\x38\xe8\x5a\xba\x9a\xe4\xd0\x8d\xb0\x7b\xb7\xa4\x45\xa8\x42\xef\x1d\x0f\x44\xbd\x7f\x78\x48\x81\x4c\x7d\x23\xa9\x75\x88\x3f\xb0\x5b\xf2\x78\x2f\x9b\x14\xa2\x06\xfe\x74\x79\x51\x13\x96\x04\xbb\x7a\x08\x02\x4c\x49\x8e\xc8\x99\x8c\x99\x27\xa0\x4b\x8d\x19\x3c\x4d\xf2\x50\xc5\x46\x03\xf8\x78\xe3\x68\xb1\xf1\x35\x85\xf6\xa1\x6a\xe0\x08\xfa\x97\xc7\x02\x85\x8f\x70\x1c\x99\x6e\x07\x30\x5d\x2d\x03\xd1\xa1\x36\x24\x6a\x60\x77\x44\xd1\x1a\xf0\x54\x5b\x8a\x70\xdb\xf4\x48\x8f\x34\x2f\x65\xa0\x5d\x45\xbf\x5a\x69\x20\x7b\xef\x0c\xd2\x14\x6f\xa1\x8e\xea\xd7\xc6\x45\x1b\xfe\x27\xc9\x26\xe4\x50\xe5\x70\x80\xd0\xe7\x01\xe8\xec\x5c\x2a\xd4\x47\x83\x4d\x38\xc0\x2d\x7b\x05\x1a\x93\x46\x51\x6f\x04\xfb\xc9\x20\x6a\x55\xa0\x94\x00\x1c\x58\x55\xf9\x6c\x57\xb8\xed\x65\x4e\x39\xe2\x98\xa1\x05\x24\x1a\xee\x1d\x8d\xdf\x57\xe9\x8d\x6c\x8d\x3e\xaa\x4c\x3b\x1c\x58\x4c\xa1\xa4\x3a\x9c\x8a\xe1\xc5\xf4\x92\xf0\x63\xcd\x10\x4c\x8d\x83\x17\xdd\xa0\x6e\x4f\x4b\xa5\xf4\xb4\x94\x92\x47\xec\xc3\x30\x50\xf9\x58\x06\xa6\xc8\x2d\xa0\x59\x36\xfc\x86\x05\x7a\x55\x42\xbd\xea\x21\x5e\x3d\xc0\x74\xbb\x4f\x81\x1e\xa3\x93\x10\x7d\xbb\x0a\x9f\x10\x32\x0b\xda\x42\xa6\x3d\x38\xc8\xd6\x70\xa6\xc1\x1a\x7c\x85\xb2\xbe\x5e\xe8\x20\x9a\xa3\xd2\x09\x0d\xb6\xc0\x34\x61\x6e\x6f\xff\xcc\x35\xc0\xe1\xee\xf1\x35\x43\xa6\xe5\x52\x20\x97\x59\xd2\xb7\x26\xa9\xb4\xc9\xa1\xfd\xbd\xf2\x65\x01\x64\xf8\x21\xd8\xae\xe8\x7f\x4e\xeb\xec\xd4\xd7\x6f\xa7\xc8\x4b\xc9\x75\x96\xe2\x3a\x83\x26\x87\xf0\xb0\xf1\x33\x7d\xbc\xf1\xf2\xad\x34\xa8\xa9\x69\x11\x42\x24\x3c\x6c\x20\x5c\x4d\xc6\xd3\x86\x56\x16\xf3\x4d\xa3\x8d\xeb\xbb\x0d\xb2\xd6\x43\xec\x19\xd3\x15\x63\xe7\x88\x4c\xd6\x79\xbb\x19\xf2\x13\x31\x32\xbc\x40\x78\x89\xef\xdd\xed\xbf\x44\x58\x82\xfe\xcb\x2c\xc6\x5f\x4b\x90\x35\x09\xf9\x22\x44\x2d\x0f\xbd\x8b\xa8\xe5\x52\x56\xf9\x0d\x7a\x40\xff\x24\x7d\x75\xd9\x9e\x76\x68\x59\x4a\x39\x8c\x97\x15\xf1\xb2\x2d\x30\xcb\x50\x1e\x56\x20\x87\x02\xf4\x8a\xac\x50\x22\x81\x61\x09\x85\xd9\xcd\x1b\xc9\xea\xa9\xdd\x80\xe4\xe3\xb2\x8a\x57\x84\xc8\xe7\x28\x27\xbf\x2f\x2b\xb3\xe4\x09\x55\xc1\xa1\x98\x19\x03\xad\xb1\xf3\x21\x82\x52\xd9\xda\x9a\x22\xd6\xb3\x09\x50\x7c\x9e\xb8\xa1\xdf\x48\xf8\x26\x3c\x5d\xa7\x5a\xbc\x35\x4b\x3b\x6e\xbd\xea\x88\xb6\x7a\xa7\x5a\xc1\x0d\x7d\xce\x4f\xb2\x70\xc4\xe9\x54\x3a\x97\x77\xb6\x8b\xf5\x66\x02\x12\xff\x28\xbf\x7f\x9e\x53\xa1\xab\xfb\xd9\xd0\xea\x36\x3a\xa0\x78\xda\x95\x9b\xe4\xfb\xc2\x68\x81\xda\xb6\x71\xdf\xda\xe7\xc8\x15\x2a\x7e\x02\x43\xbc\x9f\xbc\xfc\x9f\xbf\x8d\xb6\xff\xf3\xa5\x38\xc5\xd7\xb3\xe4\x9e\x50\xf8\x80\x63\xff\x15\x12\xc3\x48\x1c\x2f\xd1\xa4\x6a\x44\x3d\x14\x4f\x84\xc3\xff\x77\x98\x51\xdd\x36\x4e\x09\xd6\xd5\x80\x66\x35\xb5\x6d\x55\x92\x54\x8a\x9b\xa9\x8c\xec\x26\x01\xe6\xf6\xe7\xd6\xbd\x2a\x4a\xe6\x86\xd6\x75\x6a\x7e\x69\x9d\x3b\x46\xa8\x14\x5f\xad\x84\x73\x86\xf1\xa8\x29\x9c\x3d\xf3\x0c\x63\x1f\x2e\x5a\x0d\x36\xb7\xc1\xb7\xce\x29\xc4\xdf\x66\xf1\xf4\x76\x55\xbc\x48\x1a\x8d\xb3\xa5\x14\x67\x16\xda\x99\x8f\xed\xed\xd6\xc0\xd3\x13\x18\x42\x8d\x16\x5f\x73\x82\xc5\xfd\x57\x26\xd2\x3f\x77\xe3\xfe\x77\x3b\x9d\x49\x28\xba\x2f\x5a\x33\x34\xee\xff\xd4\xe1\xe6\xa3\xc5\xa8\x3f\x03\x6f\x0d\x86\x77\xca\x3e\x50\x1b\xec\xb4\x14\x56\x61\x64\x43\xf0\xcf\x5d\xbb\xb9\x49\x51\x44\xdd\x3b\x51\x8b\xdb\x7a\xc5\xc7\xe9\xdc\x68\xbb\xd9\x6b\x6d\x8a\xcb\x68\xae\x34\x73\x5d\x3b\x04\xd7\x3d\x4c\x0b\x0b\x99\x8c\x2b\xc7\xe6\xe0\x84\x46\xee\x63\xeb\x7e\xb4\x05\xb6\x64\x27\x65\xa6\x7d\x89\x44\x4d\x61\xa3\x6e\x6d\xa1\x76\x90\x63\x06\x2d\xbc\xf9\x59\x18\xa2\x8f\x66\x99\xaf\xcd\x92\x8f\x3b\x76\x26\x72\x02\xc3\xf4\x06\xee\x22\x8c\x56\x03\x75\xe3\xee\xac\x42\x3e\x97\xde\x93\xd5\x95\x5a\x6b\x13\xa1\x15\xfc\xe2\xb9\xc8\xeb\x8f\xb0\x46\x75\x57\x1e\x1d\xc4\xe5\xaa\x6d\xec\xd8\x3d\xe9\xed\x81\x83\xa9\xdd\x01\xca\xd8\x7f\x0c\x32\x88\x17\xfb\xfd\xcd\x32\xad\x46\x0d\xbb\x7a\xb5\x7b\x3b\xab\x14\x08\xd2\x3d\x65\xfc\x18\x02\x83\x3b\x97\x73\xe5\x14\x98\x94\x4a\x6b\x06\x38\x91\x2e\x05\x28\x48\xfa\x0e\xb6\x0d\x16\x5d\x6b\x2a\x92\x2a\xde\xb3\xcd\xe9\xb9\x04\xa1\x6e\xaa\xd9\x68\xa8\x90\x5c\xf1\xa7\xaa\x38\x19\x3d\xa8\xc2\xd4\x35\xae\x2b\x2d\x88\x6a\x53\x56\xcc\x96\xeb\xfd\xe7\x79\x8d\x66\x7a\x3c\xd7\x78\xb4\xb0\xd5\x93\xd6\x95\xd1\xb2\x25\xc3\x7e\x9e\x68\x61\x86\xa2\xff\x79\xa7\x4f\x66\x84\x6b\xe1\xbc\xde\xe7\x55\xbd\x50\x0a\x23\x40\x37\x15\x0d\xcd\x1b\x1a\xb2\x4a\x48\x6a\x21\x74\x2b\x61\x69\x41\xb4\x90\x1a\xa9\x84\xa6\xa4\x5f\x06\xcb\x14\xaf\xae\xba\x6e\x10\x7d\xe5\x03\xef\x63\x67\x17\x01\xb3\xc4\x48\x21\xc8\xd8\x0c\x8a\x01\x1c\x69\x74\xd6\xf2\xca\x0b\x3b\xa2\x0a\x0b\xeb\x2a\x23\xd9\x21\x38\x42\x93\x50\x6e\x1c\xe5\xdb\x9c\xaf\xab\x32\x3b\x16\xf6\x0f\xc9\xad\xaa\xbe\x45\x37\xe5\xc0\x9c\xce\x94\xd9\xb4\x9a\x10\x28\xd1\xb1\x9a\x0f\x23\x96\x0a\xb7\xba\x2e\x2c\x90\x1a\xb3\x5b\x09\x7e\x03\x14\x01\xf2\xb6\xdd\x40\x37\x6d\x35\x9e\x04\xd8\xf2\xa9\x2c\xa7\xd9\xc8\x07\xea\xd7\x36\xe3\x98\x7b\xf4\x90\x6d\x1f\xcf\xc6\x62\x77\xe2\x17\xaa\x8f\x34\xdb\xc4\x60\xea\xb0\xed\x66\x0b\x63\xeb\x03\x2f\x9f\x8b\xeb\x12\x65\xab\xa3\xb3\x61\x55\x4e\xa7\x9f\x50\xe1\x84\x8c\x41\x06\x93\x30\xb7\x21\x47\x46\x99\x3a\x5f\xb4\x01\xe4\xed\x59\x65\x2c\x35\xed\x89\x65\x42\x9b\xe3\x9a\xec\x20\x5e\xc5\x10\x01\x70\xb0\x6b\x10\x51\xa3\x0c\x73\x08\x58\x7c\x2d\xf7\x24\x97\x40\x7d\x26\xf5\x49\x66\xc9\xfd\x15\xeb\x29\x93\x3f\xe6\xc6\x20\xf3\x79\xe7\xd7\xa3\x8f\x07\x27\xbf\x5e\xfd\xb2\xf7\xf1\xe0\xc3\x61\x6c\x81\xdc\xec\xf2\x50\x72\xaa\x3a\x5b\xfc\xd2\x45\x32\xa2\xfb\xd6\xfc\x41\xbf\xc8\x84\xdf\xc3\x65\x37\xd2\xca\x2a\x25\x9b\x9b\x90\x2c\xaf\x5b\xa9\x34\xc9\x34\x69\x57\xa2\x89\xa1\xdf\xc1\x63\x16\x6a\x55\x57\xbb\xb5\xf4\x81\x4d\x9e\x73\x66\x74\x56\xc0\x53\x2b\x7d\xed\x70\x77\x0c\x34\xc8\x45\xec\xa7\x73\xf8\xfc\x19\x65\x0c\xf9\x83\x27\x17\x32\x2b\x8b\x1c\x86\x94\xa7\x10\x43\x29\xf8\x54\x66\x1d\xee\x53\xb7\x44\x52\x88\xa0\xa6\xaf\x03\x76\x63\x63\x17\xd9\x86\x74\x31\x7d\xa8\x8e\xd4\x39\x1d\x8a\x69\x69\x51\x2a\x3a\xfb\x8f\x7b\xae\x95\x76\x58\x92\x18\x0b\xcf\x86\xd3\xbb\x7b\xd4\x18\x98\x66\x68\x8e\x5c\xd0\x59\xbd\x0d\xcc\xdc\xb0\xde\x78\xfd\xe6\x31\x3b\x1f\xaf\xfc\xd6\x5e\xf0\xf1\x4f\xed\x4d\xfa\xa9\x96\x1e\x4d\x4b\xee\xc6\xa2\x8e\xfb\x6c\x2a\xb4\x66\x4d\xc3\xc6\x4f\x86\x18\xfd\xa7\x39\x8b\x0b\x7d\xfc\x61\xf3\x6c\xc5\x9c\x8d\x33\xdc\x9a\x37\x10\x72\xa3\x5d\x1f\x6b\xc4\x44\xfe\x74\x0e\xce\x43\xb5\x86\xf5\x69\xb1\xd4\xcf\xf0\x62\xe6\x5a\x88\x74\x33\x19\x1e\x13\x49\x97\xca\x3f\xea\x1f\xc4\x61\x92\xfd\x70\xb0\x8e\xc7\x42\x17\x43\xa6\x7d\x32\xb6\x77\x90\x86\x99\xa5\xbd\x7d\x48\x93\x15\x7b\xf7\xb0\x0d\xf8\x26\xde\x5d\x05\xb8\x54\xc3\xcf\x97\xc6\x06\x45\x50\xcb\x62\xcb\x41\xa4\xb0\x8b\x8e\xa7\x6e\x84\xea\xd9\xb8\xb2\xc2\x1b\xa7\x85\xda\x8e\x72\xfa\x3d\xce\x9b\x51\xb2\x6b\x62\xcb\x2a\x46\x34\x3a\x26\x1e\x5a\x71\xd8\xf6\x78\x6e\x05\x18\x53\xe4\xb1\x15\xaa\xb0\x1c\x26\x26\xcc\xc3\x75\x7b\x14\xda\xda\x0c\xe2\xd3\x7d\x50\x76\x5b\xec\x39\xf4\xe5\x8d\x63\x21\xe7\x37\xca\x6b\x4c\x2d\x58\x16\xdf\x3d\xf1\xc0\x6b\xeb\xd5\xb5\xcc\xbe\xbe\xfb\xd1\x4b\x82\x68\x85\xfd\x21\x8b\xae\x32\xd4\xf0\x7b\xea\x41\x2e\x65\xc4\xf7\x6e\xa2\x92\x68\x1b\x3f\x36\x51\x95\x4b\x70\xc8\x0c\x31\x21\x62\x9a\x55\xa7\x41\x32\xcd\xa2\x03\x72\xb8\x37\x24\x3e\xc4\x3a\xe2\xc2\x51\xa1\xd6\x99\xc2\xee\x98\x5e\xe7\xd3\xbc\xe1\xc2\xdb\x50\xa0\xad\xad\x50\x3a\x23\x41\xf9\x24\x41\xf7\xa1\x48\x60\x6b\x8b\x40\x96\x38\x10\x79\x24\x60\x3b\x35\x60\x92\x93\x12\x1d\xcd\x57\x4b\x76\x3e\xdf\x1b\xb2\x4e\xca\xe1\x28\x27\x43\x06\xb6\x3b\xd1\x95\x39\x2a\x48\xa9\x91\xce\x81\x6d\x74\xe1\x50\xc3\x16\x51\x4b\x33\x12\xd6\xc7\x0b\xa1\x81\xfb\x08\x42\x30\xa6\x2b\x14\x6f\xfb\xa0\x59\xbb\x4b\x17\xaa\x51\x42\x12\x13\xd4\x11\xc9\x4f\x75\x94\x0f\x57\x38\x8c\x48\xa0\x6a\x15\x8f\xc4\xb2\xe7\x56\x60\x80\xe2\xdc\x02\x4f\xe4\x05\xdd\xee\x76\x57\x07\xe3\x97\x04\xba\xa8\xeb\x43\xe0\x9e\x29\x3a\x91\x76\x7b\xa6\x5d\x1b\xd6\x51\x56\xf1\x0c\x72\x49\x7e\xd4\xb3\x44\xc2\x7e\x5a\x15\xa3\x68\x42\x00\xb5\x02\x0f\x8b\xd1\x4a\x5f\xa8\xb4\x81\x3f\x61\x84\x3d\xe3\xae\x58\x8e\xc7\x80\x42\x07\x85\xd4\x11\x57\xc7\xfe\x88\xc5\xdb\xa1\xae\xde\x8b\xa2\x03\xc7\xf3\x85\x84\x83\x92\x2c\x72\x44\xf5\x96\xa9\x9b\xe0\x9d\xcd\xb4\x2b\x79\x47\x93\x31\x4f\x24\xa1\x18\x43\x4b\xde\xf7\xf0\x20\xcb\xdf\xa1\x7c\x81\xff\x16\xb5\xbf\xa3\xed\x2b\x0b\x07\x99\x94\xba\xde\xa3\x92\x81\xd7\x05\x08\x77\x2a\xbc\xe3\xd2\x1c\x0e\x54\xcc\x71\x06\xc3\x60\x84\x56\xa2\xd1\xac\x3f\x38\x4c\x78\x92\xe4\x51\x41\x9b\x5f\x35\x32\xa5\xc6\x89\x0d\x37\x77\xd0\x31\x44\x27\x9c\x6a\xd9\x0d\x98\x5a\x1a\xc0\x54\xae\x5b\xaf\xb6\xba\x9b\x5d\x20\xb6\x60\xf8\xda\x24\x2d\xee\xef\xd0\x76\xe0\x50\xb4\xb8\xcf\x3b\x8b\x21\x68\xc0\xde\x7d\x27\x7c\xf4\x0c\x22\x88\xa9\x7b\xf5\x98\x5b\x34\x2f\x2d\x9e\x6c\x2f\x0c\x14\xef\x77\xaf\xa3\x96\xd8\xc0\xf2\x18\x94\x56\x7b\x78\x02\x86\x5e\x9e\x3c\x3c\x64\xd4\xd9\x3c\x38\x5e\x59\x63\x40\xc3\x81\x0a\xca\xf2\xcb\x1d\xfa\x92\x94\x0b\x39\x60\xa1\x55\xe0\x23\xa0\x17\x93\xd6\x1d\xbb\x2c\x9a\xd5\xa0\x94\xb6\x22\x5e\x6b\xe7\x21\x6a\xcd\xa8\xf9\xee\xaa\x54\xaa\xfa\xee\xc2\x04\x59\x5e\x43\xdb\xc3\x1d\x4c\x9b\xd6\xbc\x9f\x41\x0e\x13\x38\xb6\xd8\x8a\x08\x4b\x7d\xac\x18\x87\x25\xe5\x5f\x92\xd3\xd2\x71\xc8\xf5\x40\x64\x39\xcb\x50\x42\xe2\x43\x22\xc0\xad\xac\xc2\xf6\x88\x35\x46\x93\x6a\x50\xfc\xac\x26\xec\xd6\xd6\x26\x56\xb3\x88\xe8\x3a\xd8\xc8\xda\x75\xa5\xec\x0b\xf5\xa1\xbd\xd4\xf4\x1a\xd0\x80\xd7\x66\x11\x28\xfd\x4d\xa5\x7c\x11\x98\x4b\x2d\xb2\xce\xda\x19\x14\x6f\x93\x54\xa9\x7a\xe2\x10\xa6\xb2\xbf\xd2\x28\xaa\x20\x46\xdf\x1e\xab\x41\x48\x23\x52\xe5\xd1\x6f\x11\x69\x81\xca\x3b\x3e\xab\x0f\x2b\x0b\xe1\xae\xc4\x3b\x79\x5b\xd5\x58\x5d\xd0\x2a\x7d\x3c\x32\x52\x09\x10\x99\x8f\x7e\x19\x83\x33\x8b\xe4\xf5\x7d\x8a\xc3\x17\x0d\xc6\xe1\xf0\xe1\x41\x76\xb1\xb9\x1d\x86\x66\xcc\x93\xe1\x6e\x1d\x2f\x91\x27\x1d\x0c\x26\xc9\x1c\x8d\x92\xe4\x9d\x2e\x11\x9e\x7c\x6b\x6b\xc2\x73\xab\xe4\x27\x28\x25\x1c\x25\x05\xa4\x1b\x42\x3d\x91\x6d\x4d\x92\xcd\xfe\xc3\x03\xc5\xc9\x06\x8d\xc3\xe9\xf6\xf6\xcf\xb7\x52\xcd\x77\xde\xc1\x06\x7b\xb1\x16\x83\x5e\x00\x59\x4e\xd4\x68\xdc\x26\x88\x57\x30\x4b\xee\x9b\x20\x36\x07\x9e\xd3\x7e\x15\xce\xbd\x60\x37\x21\x6e\x6f\x56\x44\xcb\x09\xac\x9a\x6d\xdb\x19\x6d\x83\x5e\x31\xa1\xb3\x25\x2a\xbd\xba\xd6\x6a\xe3\x6a\xa3\x7e\x94\xba\x27\x55\x6b\x69\x22\xfa\x66\x66\xbe\x7d\xd1\xb7\xd7\x4c\x16\xc5\x0b\xad\x10\xa5\x24\x09\xb7\x59\x55\x03\x31\x54\x28\x18\x6b\x50\xcf\x78\x46\x0f\xca\x4d\xda\xf2\x70\x7e\x94\x94\x60\xb3\x2f\x88\xe2\xb2\x6d\xd2\x14\x4e\xe4\x74\xb1\x0f\x81\x10\x15\x99\x42\xce\xbf\x96\x9f\x80\x6b\x68\x1b\x29\xe2\x06\x3a\x0d\x61\x52\x71\x91\xfc\x9d\xc0\x02\x82\x80\x43\xa8\x04\x2b\xab\x3d\x25\x70\x6a\xe5\xd5\xca\x67\x25\xae\x94\x4c\x13\x58\xe5\x59\x59\xa8\x6f\xa1\xaf\x87\x14\xf7\x11\x76\x91\x83\xac\x1e\xc2\x1e\x98\x92\x60\x7e\x29\xf2\xda\xa4\x3a\x19\xc7\xa9\x38\x3b\xfc\xb4\x77\xba\x77\x7e\x72\x1a\x4f\x3c\x42\x85\x0e\xfe\xba\x2d\x9e\x7f\xf5\x34\xed\xdb\x7b\x56\x81\x76\x6d\x6b\xd1\x08\x8d\x44\x0c\x30\x54\x45\x3a\x55\xa2\x06\xa9\x57\x4a\x33\xca\xcb\xea\x76\x7c\xb7\x12\x30\x16\xbe\x0f\xb4\x32\x60\xf7\x97\x75\xd6\x14\xe0\x74\xd6\x2e\xf3\xde\x26\xbc\x7a\x9a\xef\x28\x65\xe8\x34\xbd\x23\xd9\x09\xec\x67\x2a\x5f\x96\xf6\xe9\x68\x79\xf9\xd3\x4c\xe0\x2d\xfa\xb1\x4b\x39\x4b\x82\x90\x8e\xa6\x59\xf5\xdd\x2b\x92\x1e\xdc\xef\xff\x72\xb8\xff\x97\xb3\xcf\xc7\x64\x7d\x4c\x86\xc7\xe8\xa8\x77\x91\xbe\xa0\x86\xbf\xa0\x6b\xe7\x7a\x39\x0b\x44\x3a\x1a\xed\xcb\x97\xf3\x92\x55\xbf\x3d\x6c\x77\x65\xb1\x6f\xa8\xc2\x49\xea\xa5\x61\xf0\x36\x10\x01\x6a\x58\xf4\xda\xc5\x6d\xff\x29\x09\xfe\xb4\x9d\x6d\xff\x29\x78\xfb\x27\xa4\x34\x69\x71\x9a\x41\xc5\x5b\x25\xd8\x1c\x1e\xb2\x16\x4a\xcd\x3d\xf4\x65\x0a\x7b\x19\xb2\xf5\xc0\xd5\xd6\xa8\xd1\x0f\xac\x7a\x7f\x47\xb9\x68\xb0\xab\x58\xe2\x16\xe5\x8c\x65\xce\x73\x5f\xf5\x11\xb0\x37\x74\x87\xf2\xea\x79\x4e\x2b\x6c\x77\xd5\x6b\x76\x49\x32\x6b\x2a\x8c\xc7\x1f\x4d\x13\x2b\x67\xaf\xab\x22\x73\x17\xaf\xfb\x56\xca\xa4\x13\xed\xd4\x68\xf7\x45\x3f\x2e\xbc\x5a\x8b\xe7\x36\x4f\xbd\xb5\xf5\xbb\xbe\x7e\xf0\x3a\xa1\x48\xa5\x96\x16\xe9\x2c\x7d\xf0\x38\x49\x97\xc3\xf0\xe1\x22\xbb\x64\xd8\x69\x20\x74\x9f\xc2\x4d\x52\xf6\x80\x3d\x0d\xc3\x93\x85\x64\x35\xf9\xc5\x68\x92\xba\xd7\x16\xe6\xdc\xba\x70\xc6\xb4\xf9\x1e\xee\xd1\x4d\x49\x0b\xee\x9f\x2b\x42\x15\x2e\x98\x4e\xcb\x7b\xe5\x0f\x17\xc5\x25\x71\xec\x76\x1e\xf0\x85\xac\x9c\xc3\x52\xe9\x6a\xb4\xda\x8a\x1c\xd6\x34\xfc\x70\xb1\x40\x85\x06\xd8\xb9\xf1\x29\xf9\xdd\xdc\x75\xe1\xde\xc6\x30\xd9\xd4\x6c\xfb\x2a\x7b\x68\xfa\xf3\x90\x6f\x6a\x23\xfb\x7e\x56\x75\xc8\x55\xaf\x75\x81\x0a\x3d\xcc\x5a\xf4\xbe\xbe\xe7\xfa\x64\xa8\x76\x46\xf5\xc9\xfc\xf5\x51\xc3\x10\x35\x18\x1f\xde\x7b\xa3\xfb\x4f\xc8\x30\x46\x89\xe6\x74\x0a\x3b\x97\xc6\x0d\x5e\xc6\x3a\x21\x5b\x5b\x27\x30\xbe\x0b\x35\x13\x37\x77\xe4\x96\xbb\xd9\x77\x54\xc7\xf4\xcd\xbe\xdb\x1d\x63\xd3\x1d\x18\x61\x4d\xc6\x29\xb1\x58\xbb\xe4\xd5\xea\x1f\x50\x9f\xd8\xce\x90\x14\xa8\xfe\xc1\x57\x32\xd7\xbd\xd6\x36\x09\x4d\x1a\x47\x12\x86\xe1\x1f\x2a\x4f\x99\x3c\x73\xf4\x9c\x9a\x9b\xfe\x7e\xcf\x35\xcd\xa5\x14\x95\x38\x46\xd7\xa5\x57\x79\xad\x2f\x52\x60\xb3\xfd\xbd\xe7\xb1\x0e\x42\xf9\x3c\x2a\xe2\xe9\x32\x6e\x9b\x10\x09\x67\xbd\x4e\xd0\x23\xeb\x02\x80\x5c\xd2\x4b\xf0\xd4\x91\x84\x0e\x95\x7c\x46\x15\x89\x75\x79\xa8\x1b\x81\x9c\xe5\x50\x33\x9f\x70\xf8\xe6\x51\x81\xad\xa3\x09\xd5\xb0\x7e\xf1\xc8\xd4\x51\xf7\xa9\x2d\x6b\x97\x06\xd0\x65\xe3\xa3\x86\xf8\xd8\x45\xc7\x6b\xdf\x20\x1e\x7a\x62\x59\x9d\xc3\x86\xc8\xe3\x6d\x41\x6d\x44\x0d\x9c\x3c\x29\x39\xb6\x31\xf2\x74\xdf\x55\x0d\x90\x3c\x16\x10\xd2\x7d\x7d\x03\x26\xcf\x08\x95\x8f\x2d\xc0\x60\xbe\x30\x31\xc0\x78\x0d\xb1\xde\xb9\x96\xe1\x69\xae\x49\xf6\xce\x51\xa1\x17\x94\x01\xc9\x63\x75\xcd\x45\xae\x98\x6a\x5b\x16\xfe\xa9\xcd\xd9\x4b\x90\x3c\xc7\xf9\xbc\x86\xc9\x63\x4d\x69\xae\x75\x2b\xb3\x8f\x2d\x1d\xb3\xeb\x9e\xe6\xfa\x10\x2b\x6f\xd6\x46\x1e\x11\x1f\x50\x59\xe6\xef\x49\x5f\x7c\x4e\xde\x88\xf7\xf8\xf2\x0e\xff\xfd\x82\x56\xc3\x72\x79\xfd\x8e\x06\x47\x0a\xdf\xe5\xdd\x9d\x7d\xb4\x78\x2f\xf8\x7e\xec\x98\xaf\xda\x1a\x5b\x38\x6a\x47\x88\x2b\x36\x3c\x73\xb0\x35\x3c\x60\x23\x72\x45\xff\xde\x73\x32\x04\x32\x64\x9d\x5e\x4e\xb5\x4a\x86\xea\x6e\x66\xd5\xa8\x34\x51\x6d\x6d\xe9\x04\xfb\xe9\x74\x7a\x9d\x0e\xbf\x58\x29\x2a\x44\x3f\x5d\x10\xe8\xc9\x0d\x5e\x9e\x55\xfe\xda\x20\xc1\xcc\x48\xe3\x12\x45\x36\x74\x77\x9c\x24\x7f\x27\x95\x47\xf3\xfe\x19\x66\xf8\x0d\x94\x85\x16\xfb\xd6\xf5\xa2\xac\x34\xf9\x0f\xd2\xb4\xd6\x14\x27\x67\x46\x68\x74\xca\xde\xa3\x6d\xe9\x42\x14\x54\x2b\x1f\x08\x49\xc7\xb5\xe8\x91\x84\x22\x46\xae\xee\xf7\x5e\xbb\x45\xa4\xc5\xad\x0a\x39\x6b\xde\x37\xde\xd2\x89\x18\xb3\x43\x65\xbd\x26\xe6\xb1\x2c\xe8\x13\x5a\xf3\xb7\x94\xbf\x25\x6b\xf9\xfe\x02\x0e\xef\x11\xa1\x13\x54\x8a\xcc\x56\x4d\xab\x7c\x8c\xfd\x02\xc4\x53\xef\x23\x30\xb8\xbe\xc9\x80\x52\x35\x2a\xd3\x6b\x6c\xf1\x7b\xaf\xe9\x80\x62\x8f\xf6\x3e\xa5\xf4\x90\x02\xc7\x93\xa1\x5c\x3d\x45\x66\x07\xad\x5a\xb0\x39\xd9\x48\xce\x53\xd4\x79\x5a\x26\xf5\xd6\xd6\x66\x25\x86\xdc\x57\xbe\x7e\xa6\x56\x2f\xfd\x35\x30\xf8\xef\x12\xfc\x7d\x18\x89\xe1\x4a\x68\xd5\x66\x32\xad\xc2\x4c\x1f\x1b\xb5\xbb\x86\xc2\x95\x6d\x44\xf5\xbb\xd4\xdb\x82\xce\x60\x57\x80\x9d\x99\x93\x0d\xa6\xbf\x00\x2d\x84\xc4\x4b\x58\x2e\x04\x52\x8f\x50\x8f\x45\x16\xf3\x09\x95\x18\x7f\xef\xad\xc9\x9e\x77\xc7\x08\xe7\x45\x63\xde\x7a\x4e\x00\xb9\xcb\x6c\x86\x59\x72\xbd\x4e\x7b\x28\x12\x28\x13\xc1\x44\x2d\x21\x45\x08\x91\xef\x88\x5f\x43\x85\x4f\xff\x90\x3b\x15\xf8\x14\x92\x2f\x85\xc6\x2a\x5d\x34\x56\xe9\xc0\xd4\x53\x14\x30\x6d\x33\xcd\x8e\x14\xbb\x61\x7b\x6a\xa9\xda\x12\xf7\x23\x0d\x6f\x37\xf0\x2b\xf5\x8c\x55\xc4\x83\x3c\x72\x2e\xad\x5a\xaa\xaf\x1b\xf4\x04\x4f\x07\xfb\xad\xa2\xb0\x46\x2e\x4d\xa1\xfe\xcb\x9a\x97\x4f\x78\xcd\x8c\x72\x42\xb2\x98\x19\x44\xa8\xdf\x87\x07\x6b\x7a\x0d\xad\x28\xd4\x02\xf4\x73\x75\x9e\x71\x5b\x33\x4a\xd4\x51\xef\xec\x8e\xb2\x32\x56\x4c\xa7\x27\xcb\x6e\xa6\x72\x61\x4d\x72\x4c\xa3\xbb\x00\xcb\x26\x8e\x10\x55\x53\x1a\xeb\xb6\x29\x44\xea\x6f\x2a\x29\xfa\xb9\x41\x76\x91\x3e\x7b\xb1\x70\xed\x50\x5d\xcd\xc6\xdd\xcc\x91\x39\x7d\x8c\x25\x6e\xa0\xa3\x1a\xe6\x94\x62\x74\xc8\x16\x03\xb2\xe2\x31\xee\xbe\xf1\xbc\x31\xa0\x7a\xf8\x48\x4c\xa6\x09\x5c\x36\xc0\x11\x34\xdf\xb9\xa2\xaa\x56\xe3\xbd\x27\xde\x5f\xa4\x97\xd8\x09\xa9\x8c\x2d\x58\x88\x7b\xb1\x73\x99\xe4\xd0\x7b\x95\x1c\x6d\xa1\xec\xe7\x93\xfe\xa0\x32\xc6\xf4\x96\x25\x8a\x48\xd1\x08\x60\x7b\xfb\x72\x90\x0e\x38\xeb\x5a\x77\x53\x1a\x0d\xea\x5d\x9c\x73\xf5\x6e\xf9\xff\x75\xf7\xa6\xdd\x6d\x23\x59\x82\xe8\x99\xaf\xfd\x2b\x28\xf4\xb4\x92\x2c\x41\x34\x29\x2f\x99\x09\x1a\x56\xbb\xbc\x4c\x65\x77\x3a\xed\xe3\xa5\xab\x6b\x54\x1a\x35\x44\x82\x22\x3a\x41\x80\x05\x80\xb6\xd5\x12\xff\xfb\xdc\x25\x76\x04\xb8\x38\xb3\x66\xe6\xbd\x3a\x95\x16\x18\x08\xc4\x7a\xe3\xc6\xdd\x6f\x9c\x44\xd7\x43\x5b\x58\xd4\xc7\x8c\x9b\x18\x3f\x42\xf6\x81\x03\x2a\x44\x20\x2d\x63\x10\x68\x68\xe3\x29\xc5\x70\x5c\xe4\xc6\xf3\x21\xbb\x46\xc3\x29\x74\x5a\x29\x75\x2c\x1e\x15\xfc\xb1\xdc\x18\x3f\x80\xa7\x24\x41\x97\xc7\x39\xdf\xc5\x75\xd0\xdc\x9e\x57\x74\x21\x09\xf4\x8f\x82\xb3\xf9\x3a\xb4\x45\x0e\x94\x8e\x4d\x0c\x4d\x25\x75\xb4\x98\xd1\xaf\x5e\x81\x43\x26\x4e\xe1\xae\x7a\xd2\xb4\xb3\x84\x2a\x44\xc9\x4d\x32\x9b\x4f\xf5\x7d\x86\x46\x9f\x62\xc3\x2a\x12\x95\x4f\x82\x5e\x7f\x4a\xf1\x81\x07\xbd\xe0\x44\x4a\x43\x91\xca\xa8\x4f\xcf\x46\x61\x7d\x72\x36\x1a\x9c\x04\x7f\x2d\x7a\x7d\xf2\x8c\xab\xb0\x56\xe2\xad\xb5\x79\x67\x2c\xda\x11\x2e\x52\xbb\x24\x7c\x29\xce\xa4\x8d\x22\xd8\x5d\x1f\x6d\x7e\x51\x76\x06\x7f\xeb\x50\xe4\x44\x8b\xd6\xf2\xe9\x35\x45\xca\x12\xd2\xab\x69\xb8\x5a\x57\x37\x28\x0f\x5e\x6d\x26\x5f\x64\x3c\xd0\x37\xe4\x85\x59\xf7\xff\x16\x06\x86\x45\x51\x78\xd7\x45\xff\x74\x46\x67\xf3\x82\x8a\x37\xca\x98\x95\x77\xea\x6f\xdb\xe3\xff\xec\x34\x8c\x38\xc8\xca\xbf\xc5\x33\xc1\xdb\xb3\xbd\x0c\x23\xb6\x5a\x61\xf9\xec\xa8\x7d\x0c\x13\xbc\x7b\xb8\xcd\x9a\x42\xb3\x4b\xd1\xf8\xe1\xe3\xd0\xc7\x2d\x45\xe3\x47\xdd\x49\x3b\xbc\xba\x41\x93\x81\x82\x32\x69\xfc\xb5\x8d\x53\x8a\xc6\x1c\x2c\xba\x9b\x51\x82\x1a\x3f\xf8\x1d\x16\x2c\x36\x29\x3a\xe3\x28\xcc\x5b\xb8\x24\xa8\xf2\xd8\x67\x95\x75\x76\x88\x71\x38\xbf\x9e\x89\x00\x48\x32\xe4\x5a\xd4\x84\x1a\xf3\xb3\x74\x97\xc3\x22\x0d\xad\x70\x22\xa1\x11\xc1\x2d\xfa\xcc\x6d\xa4\x83\xd3\x71\x68\x84\x06\xe1\xaf\x55\xe0\x39\xd1\x58\x29\x7e\x6c\x5c\x7d\xe8\x61\xa3\xb1\xc2\x97\x58\xa3\xe1\x5a\xdd\xc3\x48\xfd\x63\x10\x79\xdb\xf7\x1f\x81\x11\x2b\xe5\x5b\xfb\xc7\x0b\x75\xd0\xd2\xcd\xee\x3f\x04\x33\x32\xcb\xf6\x31\xa4\x9d\xfb\xe0\x8c\xa1\xee\xe3\x00\x54\x66\xf6\xa9\x74\x16\x70\x22\x13\xf6\x67\xe1\x67\xe0\x49\x50\xd5\x66\x48\x26\xf5\xa7\x70\x19\x7e\xd6\x46\xc8\xac\x9b\xdc\x69\xdf\x67\x9a\xdb\xbd\xc1\xac\xd5\xd4\x29\xf7\x48\xee\x78\x8e\xdd\x9d\x25\x2a\x31\xad\xef\xe8\x3b\xeb\x2d\x0e\x68\x86\xd2\x80\xcf\xf8\xcf\x32\xbe\xa3\x00\xef\xd1\x1d\x93\xb3\x62\x6e\x1d\x0c\x09\xda\xb1\xa9\x33\x2d\xeb\x8a\x2a\x13\x11\x66\x4f\x10\x53\xf2\x6d\x5c\x89\x3c\x8d\x1c\xdb\xd3\x8e\xe6\x55\xa1\x98\xba\x72\x45\xa5\xc9\x40\x12\x38\x18\x67\x0b\x4d\x17\x9d\x00\x7e\x27\x09\xf0\x7e\x2b\x57\x0c\x58\x63\x70\x44\x1c\x88\x9d\x5a\xb2\x44\x37\x0f\x84\x22\x60\xf3\xca\x93\x13\x49\xc2\x65\x9b\xb0\x95\x36\xd1\x22\x1f\x17\x27\x27\x82\x1a\x3d\x1a\x91\x9d\x2f\x93\x73\xfe\x59\x4e\xe6\x8a\x21\x90\xab\x62\x38\x1b\x6c\x73\x05\xe5\xf6\xcc\x8f\x45\x86\x1e\x74\xf9\x44\x7d\x38\x27\x61\xb3\x92\x91\x12\xaf\x81\x81\xb3\xa5\x91\xf1\xe2\xf4\x34\x5c\x20\x2b\x76\x0e\x90\x17\xd5\x7d\x4e\xf4\xc8\x81\x1a\xbb\x76\x54\xce\xaf\x92\xf3\x13\x23\xb1\xbe\x12\x95\x81\x84\xf5\xf4\x56\x99\xbd\x5d\xed\xe8\x4e\xe8\xb0\xbc\xab\x07\xd4\xf1\x7c\xe8\x74\x2c\x85\x08\x14\x05\xc2\x0f\x59\x59\x98\xdd\xdf\x4b\x79\x05\x9a\x25\x84\xb5\x00\x30\xf2\xdb\xce\xc8\x38\xa1\xcb\x6f\x7b\x1d\x57\xc7\xc7\xd5\x45\x79\x09\xa0\x94\xc1\x9f\xc9\x1a\x88\xcc\xa9\xc8\x5c\xaf\x39\xb2\x75\x58\x87\xe8\x66\x25\x34\x41\xc9\xd7\xfe\xda\x84\x2e\x7c\x67\x15\xc4\xf5\x20\xea\xaf\xc9\x9d\xb9\xfb\x8b\xce\x3d\x5f\x03\xad\x38\x30\xb3\xa3\x1a\x2f\x9f\x0b\x95\xfe\x34\x04\x8a\x8d\x96\x66\x00\x44\xe0\xc9\x46\xcd\xb7\x1a\x1c\xb5\x8e\x52\x09\x2c\x47\x76\x7c\xec\x59\x05\x60\x45\xba\x46\x41\xab\x52\x9a\xb9\x42\x5b\x9b\x6a\xa5\x5e\xdc\xe7\x34\x34\x72\x5a\xad\x5d\x94\xb6\xfd\x62\xc5\xdb\xaa\x78\x73\xf5\x9e\x16\xe4\x2e\xe7\x06\xf4\xb4\xea\x90\x69\xbf\x48\x0f\xd6\x6a\x71\x20\xfc\xe6\xad\xcf\x53\xbb\x01\x12\x96\xf8\x06\x34\xb8\x2b\x77\xf4\x3d\x20\x4d\x74\x17\x4a\x49\x3c\x5f\x2b\x26\xa9\xbd\xd5\x5b\x0c\x1f\x5a\x18\x11\xd3\xbf\xb7\x30\x22\x9a\x43\xe0\x47\x13\x6b\x8c\x32\x50\x95\xb1\x44\xc4\x96\xe0\x19\x6e\x01\x83\xab\x54\xe7\x60\x57\xfa\x7c\xe0\xbe\xda\x8d\x93\x95\x67\x97\x45\x82\x7b\x1d\x45\x3f\x3c\xde\xdf\x24\xd9\x7f\x11\x02\x0d\xfc\xa4\x8b\x06\x26\x4a\x70\x97\x07\x9d\xa1\x5d\xff\x35\xbd\x7d\x93\x61\x08\x06\xd2\xaf\x57\xfd\x3b\x3b\x70\x1c\x91\x0b\x76\xb4\x38\x2a\x32\x63\xc5\x51\x81\x15\x27\x8e\xe9\x8a\xb6\x9a\x5a\x77\x16\x8d\x7f\xa4\x9c\xd2\x67\x07\xe4\x5d\x64\x31\x8a\xc7\x09\xdf\x8e\x95\xcb\xbf\x26\xd2\x26\x87\x9c\xac\x8a\x78\x65\xca\x83\xc8\x63\x1c\xb3\x61\xae\x28\x7a\x66\x3c\x25\xc9\x9e\xab\x8d\x16\xb5\xd7\xfd\x1c\xde\xa5\x5f\x7a\xb9\x0e\x2c\x25\x72\xe5\xf9\xcc\xf3\x28\xca\x11\x2a\x10\x3b\x94\xc7\x66\xec\x8b\xb9\xe9\xf4\xe6\xba\x98\xad\xdb\x8a\x15\x2b\xea\x19\xfa\x07\xa3\xa7\x2f\x3d\x2f\xa4\xaf\xb0\x37\x7d\x9c\x75\x24\xc9\xdf\xaa\x2b\x75\x9c\x2d\x4e\xd2\x35\xdd\xc4\x6f\x56\xbd\xba\xbf\x62\x11\x98\x9b\x61\xce\xaa\x05\x34\x20\xe0\xd7\x19\xc5\xdb\xeb\x0a\xd5\x10\x55\x02\x8d\x49\xad\x87\x66\xa3\x33\xf5\x86\x97\x0f\x3e\xc2\xe1\x03\x33\x9f\xd5\xd6\x3c\xa2\xc4\x70\xf9\x5d\x78\x1c\x0d\xbc\xce\x44\x1e\x33\xa1\x03\xbc\x5c\xcc\x4d\xca\x30\xb1\x25\x31\xcc\xc4\x63\x7b\xac\x7b\x38\x84\x95\x06\xe4\x23\x0d\xc8\x49\xd3\x24\xd3\xc5\xfb\x74\xde\xf1\x7e\x96\x8a\xf7\xb0\xdc\x68\xe2\xa2\xc4\xcb\x35\x94\x7d\x2c\xdb\xa1\xe7\x81\x1c\x30\x47\x83\xe6\xdf\x61\xa1\xbb\x11\x82\x12\x81\xdf\xac\xd6\x50\x14\xb2\x6f\x7b\xbe\xc0\x29\x55\x3a\xaf\xf1\x78\xa1\xd4\xd3\xf3\x1e\x75\x11\x6a\x36\x7d\xc7\xa8\x57\xe0\x0b\xcf\xa6\x1c\xe2\x18\x61\x45\xdf\x2f\x84\x03\xc4\x9d\x95\x8b\x85\x33\xc4\x94\x70\x3b\xcb\x82\x2a\xb4\xe5\x3c\xad\x25\xd8\x19\xe7\xbf\xd8\x18\x00\x78\x67\x65\x95\xb1\x65\xc2\x43\xab\x67\x3c\x1e\xee\x1a\xe0\x94\x1f\xee\xb2\x3f\x16\x66\x5a\x3e\x3b\xab\x87\x07\x04\x9a\x6c\xdd\x04\x88\xe4\x84\x89\x17\x07\x49\x13\x3f\xf0\x3a\x7a\x61\x94\xec\x87\xe9\x1f\x1e\x10\x30\xad\x31\x42\x4b\xa7\x32\x73\x2b\x1a\xc0\x22\x79\x1b\x03\x09\xfc\x4a\x24\xa3\xa6\x20\x31\xc2\xfd\xfc\x0a\x49\x5a\x25\x3b\x47\x2c\x4c\xa1\x85\x30\xe6\xfb\xdf\xd6\x19\xac\x33\xca\x14\x4f\x02\x8c\x9d\x56\x9d\x04\xff\x41\x01\x75\x8a\xb2\xe9\xd5\xab\x74\x9a\xcd\xb3\x94\xa2\x86\x05\x27\xfd\xe0\x3f\x28\xb6\xce\x7f\x0c\x03\xe9\x86\x29\x51\x77\x5f\x8e\x63\x23\x2d\xbb\xb4\xe3\xe5\x91\xb6\xf8\x2c\x48\xc0\xce\x7d\xda\x75\x46\xed\x4b\xa6\x3d\x4f\x49\xf0\xa4\x68\x14\x94\xc4\x9f\x81\x72\x45\x8e\x20\x39\xa2\x44\x05\x7c\x61\x5c\x61\x74\x8f\x75\xbc\xc4\x77\xc6\xb5\x23\x26\xfc\x53\x41\x81\xad\x60\x32\x35\xcf\xb7\xc0\xf9\x22\xfe\x00\x34\x82\xbf\xd7\xf8\x1b\xa7\x5a\xaf\x57\xab\x1c\xa7\xde\x94\x72\x5d\xc2\x1e\x6c\x25\x65\x47\xd2\x51\xe6\x06\x03\x4b\x0d\xa0\x4c\x70\x6d\x93\x2c\xc3\x36\xf7\x7a\xd8\x2c\x12\x20\x4d\xf0\x67\x4d\x93\x1f\xb8\xf7\xe1\xf6\x89\x53\x24\x25\x3b\x2e\x98\x0a\x3f\xc5\xb3\xaf\x79\x65\xb6\xcd\x3e\xf1\xcc\x5e\x6c\x70\x8d\x65\xdb\x67\x2f\x03\xc8\xd1\xf4\x25\x5f\xbb\x06\x76\x6b\xfd\xb4\x94\xda\x8a\xb5\x8c\x48\x86\x02\x8e\x12\x13\x3c\x20\xed\x09\x63\x9f\xb6\x42\x5c\x49\xf2\x64\xba\x7b\x29\x51\x0c\xa3\x7e\x34\xda\xc0\x00\xd7\xe4\xa6\xa5\xd2\x46\xc3\x29\xa9\x25\xb8\x82\xf3\xb0\x75\x49\x32\x5e\x92\xd4\x9d\xbe\x58\x96\xc2\x59\x82\x9e\x29\x04\xee\x86\x83\x66\xe0\x98\xa8\xf9\x36\x17\x47\xdf\xc7\xbd\x35\x56\xa6\x19\xc8\x4d\xa7\x3d\x4d\x50\x41\x46\x7e\x5d\xaf\xb6\xce\xa2\x34\x36\xd6\x33\x0b\x67\x23\x55\x2a\x27\x0e\x9c\x98\xec\x0d\xd2\xd3\xae\xa9\xe8\x68\xd0\xe2\x90\x62\x3c\x68\x15\xa6\x4e\x38\x09\xa0\xb1\x66\x83\xc1\xca\x8d\x7e\x26\xd6\xf1\x75\xf3\xe2\x1c\x74\x96\xc9\x89\x07\x0b\xca\xfd\x0e\x33\x5c\xec\xf8\x19\x1d\x7e\x73\xfa\xf6\x94\xf3\x83\x70\x92\x8c\x55\x07\xa8\x29\x31\x51\xd3\xc1\x38\x49\x6c\x5c\xb2\xd7\xa9\xe4\x4e\xed\x63\xc9\x81\xf2\x71\xd5\x5d\xbe\x7f\x3d\xf8\x3b\x9c\xd0\xd5\x6e\xc8\x18\x4d\x4a\x0d\x12\xa5\xc4\x13\x18\x0b\xbe\xbc\xd4\x61\xab\x12\xf5\xa9\x09\x26\x9b\x6f\x58\xca\x8e\x73\xd0\xbd\xd5\xf3\x2d\x58\x66\xf6\x7f\x02\xad\x20\x1f\xbf\x1f\x4e\x59\xfc\xdf\x81\x4a\x09\x91\x7b\xdc\x94\xdc\xe5\x7f\xb4\x81\x52\x45\x6f\x6c\x2e\xd6\xb4\xef\x53\x19\x3d\x73\x6a\x81\x63\xae\x92\x31\x6d\x76\x83\x1f\x85\xc2\xab\xbf\x64\x18\x56\x51\x47\x89\x9c\x26\x75\x1a\x14\xeb\xe5\x35\x8a\x02\xe8\x87\x88\x82\xc8\x3f\xb4\x57\x61\x24\x8d\x62\x27\xf4\xe2\x1a\x8d\x3b\x93\x42\x15\x37\x5c\x2c\x56\x31\xf2\x05\xe8\x54\xac\x76\xfa\x39\xad\x6e\xfb\x33\x23\x10\x1b\xba\x0f\xb5\x2f\x29\x6d\x88\x3b\xc1\xa0\xb0\x5b\x03\x59\xa6\xbc\x6e\x26\x1c\x2a\x63\x09\xd5\x8a\x88\x67\x2d\xc7\x3c\xde\x58\xc6\xad\xca\x25\x47\x2c\x8e\xdc\x7a\x77\x22\xe7\x01\x5d\xf1\x41\x64\xb1\xe5\xef\xd3\x9b\x57\x5f\x57\xe7\x6a\x05\x0c\xe3\xdc\xa5\x19\xbe\xa6\xb1\xc0\x8d\x53\x41\xa1\xec\xd6\x6c\xeb\x25\xb0\xac\xd2\xa9\x0c\x25\x38\x14\x61\xd5\xd3\x9b\xac\x53\xa5\x37\x00\x55\x81\x9d\x10\xc0\xb4\x8c\xd5\xee\xd6\x66\xb2\x67\x23\x9c\xa0\x19\xef\xaf\x2b\x5a\xe0\xb5\x61\x2a\xfa\x5a\xb2\x99\x68\xd4\x1a\x3c\x7d\x9a\x14\x65\x71\xbb\x2c\xd7\xf5\xb3\x67\x41\xf8\x95\x3c\x93\xbf\xc4\x80\x2c\xc2\x17\xf1\x1d\xad\x56\x94\xf5\xc5\xb2\x61\x72\xf6\x32\xc7\xdf\x12\x86\x06\x64\xec\x88\x25\x73\xdd\x2c\xc3\x24\x16\x0a\xe8\x1c\x84\xbc\x66\x58\x54\x4a\x4b\x55\x06\x56\x2c\x12\x60\x3b\x08\x93\xe2\x36\xa2\x20\xb8\xd8\x1b\xb9\x00\x89\x68\x98\x98\x5f\x5e\xac\x20\x14\xaf\x43\x54\xff\x63\x96\x79\x6a\x0b\x4a\xf2\x10\xae\x3b\xf8\x3b\xe5\xbf\xb8\x04\xd1\x2a\xac\x17\x09\xfc\xb5\x44\x02\x2f\x76\x45\xfc\xf2\x87\xb9\xdb\x1e\xc9\xce\x5e\xd6\x68\xfc\x84\xf4\xb3\x0f\x0f\x08\x44\x27\xc4\x8e\xb9\x08\x91\x52\x7f\x2c\xdf\xad\x1b\x8c\x19\x65\x38\xf1\xdb\xf1\x8e\xca\x9d\xc6\xd3\x89\x57\xcc\x34\x49\xfa\x95\x19\x8d\x48\x58\x9f\x42\x77\x32\x3e\x4b\x5b\x3c\xdd\x1e\x9a\x50\x5a\x6a\xe9\x2c\xaa\x2d\x61\x8d\xfe\x35\xbd\x8d\x52\x7a\xe2\xe0\x35\x05\xa5\x54\xd4\x6d\x5b\x39\x4f\xe5\xf9\x6f\xe0\xee\x6c\x9e\xfa\x7a\x11\xb7\x69\x23\x6f\xd3\x34\xf6\xd4\x42\x83\xfd\x72\x68\x74\xd2\x4f\x87\xa6\xe4\x7b\x28\x06\x26\x9e\x68\x60\x03\xf6\xd2\x4f\xad\x44\xb1\xdd\x23\x88\x47\x9b\x70\x4b\xd8\x26\x6a\xa9\x3f\xc0\xf0\x4b\x99\x1d\x7e\xa9\x32\x0d\x39\xaa\x2d\xe2\xa8\xae\xd8\x36\x1d\xd6\x1d\x04\x5f\x07\xf8\xfc\xa8\x81\x66\x45\xd6\x64\x80\xa9\xff\xcb\xb4\xd6\xef\x0f\x64\x8a\x07\x54\x5c\x7c\x2c\x3f\x34\x00\xe4\x53\x36\xcd\xc0\xfc\x27\xe2\xa5\xb4\x7d\x81\x81\xcd\x6e\xad\x40\x41\x6c\xd8\xcb\xd9\x1f\xf4\x3e\x90\x3d\x06\x47\x02\x94\xfe\x04\x26\x3c\x4b\x83\x67\x69\xe4\x5e\xfa\xc0\x3c\xd9\x09\xe6\x66\x4c\x18\x4a\x78\x6d\x06\xb9\xb0\x72\x0d\x3b\x23\xd3\x01\x61\xec\xdc\xed\xb9\x5f\x3c\x4b\xd1\x19\xe5\xe2\x45\xb5\x15\xfb\xc1\x08\x36\x81\x91\x3f\x6b\x7c\xef\x06\x81\x40\xd1\xad\xd9\x42\x4b\xd1\x94\x0c\x55\xb4\x2b\x6d\xc2\x9b\x0c\x75\xa4\x2c\xb4\x37\x43\x73\x70\xee\xc1\xd2\xba\x98\xb5\x28\x20\xe4\xa2\xab\x2f\xdf\x5e\x2a\x00\x76\x9b\xee\xa8\x5e\x94\x0d\xf0\x2f\xcf\xf3\x1c\x61\x1e\x25\xbc\x5b\xba\x72\xe1\x61\x57\x5f\xad\xfa\x26\xf6\xa0\xfe\x3e\xc7\x17\x33\xcc\x84\x19\x2e\x48\xb7\x8f\x19\x59\xf4\xfe\x09\x41\xb4\x2f\xb7\xf2\x67\x6d\x1f\xa6\xe7\xe2\xa9\xe7\x9b\x32\x7d\xea\x02\x50\xd7\xb7\xee\x14\xba\x70\x87\x8e\x9b\xe5\xeb\x72\xe0\x3f\x76\x24\x58\x5a\xdb\x5f\xba\x1d\x76\x1d\x45\x56\x5c\x4d\x72\xeb\x06\x98\x0e\xc9\x3a\x22\x5c\x62\x20\x86\x9d\xc8\xcb\x3e\xb4\xd1\xe3\x1f\x0f\x8e\xd6\xb5\xcb\x5e\xcd\x39\xc3\x70\x0d\x6b\xfb\xaf\xd6\x11\x86\x1b\x98\xec\xb0\xec\x9c\xed\x8f\xbf\x27\xfc\x78\x80\x7d\x14\x6e\x86\x92\x91\xd7\x1c\x81\xd7\x97\xb6\xaf\x1d\x55\x07\xea\x13\xee\xda\xee\x77\x74\x67\xab\x2d\x5d\xb5\xa7\x56\x7a\xba\xfa\x4d\x7e\xab\x25\x8d\x6d\x08\xee\x0f\xa4\x07\x09\x07\xd3\x2e\xdb\x56\xde\x8e\x14\x5a\x49\xe1\xd1\x43\xad\x69\x4d\x11\x8a\x5a\x96\xdf\xa4\x32\x98\xa6\x56\x60\x28\x67\x0e\x2a\x2c\x68\xab\x45\xf2\xd6\x44\xe6\x8c\x33\x3b\xc4\x2a\x10\xbb\x64\xd6\xb2\xa1\x6d\xfe\x06\x03\x4b\xd0\xd1\xa0\x46\xb5\xbe\x35\x5a\xb4\x2c\x18\xba\x23\xe9\x73\xf7\x61\x8d\x2a\x86\x9d\x0b\x04\x18\x44\xb8\xb4\x71\x77\x3f\xcd\x7f\x49\xd1\xe6\x29\xb1\xe2\x3e\xb3\x7b\x75\x57\x45\x52\x5f\x0c\xda\x01\x4e\xf7\x30\xa1\x44\x78\x01\xa8\x7d\x42\x10\x7a\x48\xe4\x53\xf1\xda\xa3\x0d\x3d\x87\x15\xf0\x69\x5c\x06\x11\x1d\x68\x57\x67\x84\x2a\x20\x2b\x68\x46\xb6\xa3\x71\xba\xdd\xa1\xad\x2e\xa5\x91\x6c\x50\x80\xb0\x3a\x07\xd2\x53\x2f\x41\x5d\x45\x62\x9c\x2f\x6f\x2a\x1f\xca\x90\x23\x92\xdb\x72\xc8\x23\x34\x8f\x91\x90\x82\x89\xea\x5c\x20\x71\x9a\x51\x91\x41\x54\x02\x0b\x99\x9c\x07\xed\xac\xa1\x71\x2a\x81\xbf\xd8\x96\x86\xaa\x7d\x06\x93\xb9\x83\xd1\x3b\x9f\x18\x3b\x2f\x6c\x6c\xc7\x67\x4c\xff\xef\x17\x1c\x50\x28\x8c\x5e\x78\x62\x5b\x38\xe7\xd6\x17\xfe\x82\x74\xac\x59\x3b\x84\x86\xb6\xfd\xd3\xaa\xa9\xca\xab\x6d\xda\xa5\xf5\xb4\xd5\x34\xab\x7e\xd9\xe5\x63\x95\x1a\x26\x64\x89\xcf\x5d\x46\x29\x6b\x2c\x9a\x10\x89\x9a\x54\x79\x99\x3a\x54\x51\x15\xe7\x86\xdf\x58\xe5\x62\xc7\x02\xc6\x3b\x35\x12\x3d\x7a\x82\x00\xa0\x07\x2a\x37\xa0\x8c\xbb\xf4\xed\x99\x9a\x91\x6a\xb3\xbf\xd3\xfc\x46\xfb\xcd\x4f\x85\x0d\xf5\x4f\x72\xfb\x24\xdc\xa3\xa7\x85\x06\x89\x45\x1e\xbb\x5e\xad\x26\xf1\xdc\xf2\x5d\x35\x89\xe7\x0f\x64\xa6\xcf\x6e\x24\x48\x1d\x58\x14\xf3\xd4\xe7\x88\x9a\xef\x76\x25\x5d\xb5\x94\xe9\x06\x80\xde\x69\x6e\x84\xe4\x04\x55\xe8\x63\x4f\xa2\x6c\xb3\x6f\x0c\x6f\x7f\x78\xd0\x2d\xf6\xe7\x5b\xe6\x0c\x18\xfc\xc7\x2e\xd3\xf1\x43\x6d\xc2\xe9\x14\x1e\x16\xff\xef\x9b\x99\xb9\xc6\x4f\x54\x96\x7b\xf2\x72\x49\x17\x2f\xe7\x95\x4d\xb8\x0c\x5e\xb2\x9d\x19\xab\x7d\xcc\x58\x67\x6a\x4c\xaf\x3c\x2b\xff\x2d\x5c\xcf\x74\xe3\xf0\x78\x87\xb2\x32\x53\x64\xf1\x2e\x56\x61\x7e\x89\xec\xd7\xde\x7c\xc9\xfc\xff\x35\xbe\xa4\xfc\x66\xbe\x24\xf9\x4d\x7c\xc9\xda\xe2\x4b\x6a\xc1\x97\x2c\xf6\x12\xaa\xfc\x76\xbe\x64\x6f\xde\xa2\x5b\xe2\xf7\xe8\xb0\xc8\x71\x18\xcb\xab\x1c\x76\x46\xdb\x39\x3e\x9e\x4a\xc2\x95\x69\x1e\x4b\x45\x22\xa2\xca\xad\xa4\x5e\x49\xe5\xea\x12\x5e\xdc\x22\x01\x83\x66\x1d\xce\x8b\xd8\xea\xae\x1d\xbd\x87\xe3\x7a\x14\x91\xd2\x48\x99\x37\xca\xcf\xd9\x3c\x7d\x71\x3b\xcd\xdd\x83\xec\x44\x65\xf8\xc6\x5c\x18\x4e\x64\x83\x4e\x11\x4c\xcb\xf8\x6a\xde\x4e\x52\xe3\xf8\xd3\x3b\x44\xfd\xca\x9b\xc6\x4a\xae\x9a\xe9\x1d\x8c\xde\xd3\xdb\x77\xe8\xbc\x5f\x0c\xaf\x56\x80\x67\xa1\x4c\x76\x57\x9f\x7b\xca\xa4\xcb\x4c\xe4\x79\x17\xa3\x7f\x2e\x85\x7f\x22\xe3\x2a\x11\x08\xbc\x23\x28\xc0\x7e\x93\x41\xa6\xae\x35\x2c\x4f\x99\x1a\x96\xe7\x1d\x0d\x8b\xb4\x72\x72\x2c\xaf\xcb\x6a\x2a\x20\xd1\xef\x57\x1d\x06\x73\x5d\x25\xe0\x04\xd7\xa9\x6a\xd9\xf8\x1c\xe3\x96\xa0\x82\x4b\xb7\x2d\x12\x7d\xe2\x5d\xe5\xda\xe3\xaa\x8d\x09\x65\x16\x5f\xaa\x05\xed\x17\xe4\xf0\x29\xdb\xa7\x52\xc6\x27\x38\x74\xfd\xc2\x6c\x9b\x7b\x2e\x8c\x9e\x3f\xa4\xcd\x8e\x5e\x6b\x51\x23\x60\xa5\x97\x64\xd5\x7d\x3d\xdf\xdf\x77\x0c\xe8\x72\x40\x22\x6a\x5a\x6d\x1a\xc0\xc6\x1c\x00\xa7\x49\xda\x36\x00\xaa\xa1\x06\xb0\xc2\x5e\x74\x18\x18\x19\x39\x4a\x77\x2d\x4e\x1e\xe6\x09\x74\x78\x71\x38\xbb\x39\xa6\x34\x2d\x45\xaa\xab\x14\xa3\xab\x3a\x9f\xc5\xfe\x04\xac\xfd\x12\xd9\x6f\x7b\xf0\xe6\xfb\x9d\xfb\xf6\xbb\x4d\xe2\x90\x21\xb7\xd6\xdb\x09\xc4\xd1\x0e\xa9\xe6\xb4\x9c\xf2\x29\xb0\xd8\xfd\xf9\xce\x2c\xa3\x07\x39\x5d\x76\x7a\x47\x6a\xa4\x0b\xc5\x5a\x86\xe0\x7a\x35\xee\x4e\x8a\xf4\x68\x97\x5d\xa0\x25\x0b\x5b\xf6\xb7\x84\xf6\x39\x3e\xbe\xb6\xae\xa1\xfd\xa8\xd1\x59\x56\x19\x9e\xa3\xf5\xcf\xac\x56\xd1\xc9\x2c\xa6\xe6\xfd\xcd\x09\x5d\x24\x9d\x29\xe9\x8d\xf6\x50\xf6\x8d\x62\xe4\xf8\xfd\x51\xfc\xa2\x12\x6d\x5b\x31\xdc\x8c\x13\x69\x44\xbf\xef\x0a\xa3\x2a\x9d\x01\xde\x62\x8a\xcf\xd3\xd4\xfc\xe5\xcd\x4a\xdf\xf8\x27\x3f\x59\xf6\xd1\xe9\xfb\x46\x05\x5b\xbb\x19\xd6\x00\x5c\xe8\xe9\x6e\xa6\xc3\x4c\x9f\x15\x66\x1e\xcc\x1b\x34\x7d\x40\x4e\xb8\x85\xb0\x29\xb2\x89\x07\x8f\xb3\xb9\x78\xb7\x28\xab\x62\x89\x5a\x6b\x01\x81\xec\x1a\xd8\xd6\x2d\x99\x69\xdd\xd2\xd8\x5b\xa6\x44\x6c\xe8\x68\x14\x7a\x33\x2b\x9a\xbc\xb6\x19\xd7\x8c\xb7\x21\xab\xff\x88\x1b\x01\x43\x17\x3b\x41\x31\xb7\x7a\x37\x8c\x35\x9b\x01\xe7\x9c\x6d\x6d\xd7\x3a\x6c\xda\xe1\x5f\x97\x7d\x4f\x7b\x83\xf0\x56\x0d\x92\x82\xef\x5c\x61\xda\x2f\x36\xcd\xf0\xb2\x2b\x2b\x1f\x6b\x33\xdf\x2b\x22\x15\x47\x7a\xb2\x93\x01\x58\x1e\x8a\x33\x1f\xaf\xf3\xd9\x4f\xf5\x2c\xdb\x54\xcf\x4d\x8b\xea\x81\x1b\x26\xbc\x75\xce\xcd\x15\xea\xee\xae\x19\x00\x5e\x6d\xe5\x6c\xfc\xa7\x53\x82\x66\x97\xaa\xc6\xfb\xd5\x91\x06\xe9\xf3\x3e\x80\xf4\x0a\x60\x20\xc5\xd0\xc1\x9d\x5f\x0c\xc2\x17\x28\xab\xbc\xd1\xba\xd6\x4d\xf8\x75\xeb\x70\x6d\xc8\xdb\xa1\x50\xb2\x2b\xdb\xaa\xab\x2f\xf1\xc5\xab\xf0\xeb\xe5\xe4\xb3\x95\xa1\x67\x26\x38\x8f\xfd\x59\xb8\x2f\x5b\xd5\xc3\x5b\x70\x5f\x6e\x33\x4c\xd6\x58\x07\x3e\xcc\x48\x5f\xed\x13\x78\xad\x13\x69\x6e\xc3\xa7\x4c\x7b\x0a\x54\xd1\x65\xee\x2e\x96\x47\x62\x14\x91\x0c\x57\x69\x4c\x7c\x0d\xcb\xba\xdd\x35\x84\x2b\x24\xaa\xd0\x57\x4e\x06\x23\xa6\x0c\x5e\x98\xe9\xe1\x10\x2f\x4d\x24\xc0\xdc\xdf\x5f\x71\xa0\x13\x85\x4a\x85\x42\x35\xb3\x22\xd9\x29\x69\x7e\xbf\x16\x91\xec\x90\xb1\x54\xcb\x35\xc0\x98\x1f\x57\x83\x3b\x3c\x34\xc2\x97\xe8\x76\xe2\x9e\x28\x0b\x7e\x8c\xcd\xa3\x2c\xbb\x13\x18\xa2\x8c\x19\xd1\x0f\xac\x8b\x1a\x28\xe3\x1c\xd0\xd8\x1f\x2d\xdc\x15\x84\x2f\x78\x6a\xef\xa5\x0c\xd8\xb7\xa1\x76\x7a\x24\x74\x46\xdb\xb2\xfb\xda\x7f\x47\x22\xbf\x0f\x4d\x05\x7d\xdd\xdc\xb6\x9b\x59\xfa\x3d\xab\x6c\xfc\x4a\xd5\xa4\xad\x8f\x51\xcb\x83\x5d\xaf\x49\x14\xfd\x21\xbe\xeb\x1c\x1d\xcb\xa3\xed\x0e\xa2\x32\xb4\x78\xdc\x68\x1d\x7a\x96\x2a\x7a\x61\x88\xb1\xdf\x87\x49\x9d\xac\xa2\xa9\x27\xad\xe5\x6f\x97\x02\x74\x12\x6e\x7b\x05\xa3\xf0\x89\x0a\xf6\x20\xce\xf6\x8b\xcb\xeb\x4d\xaf\x63\x24\x82\x19\xbe\xf9\xf4\xe1\xe3\xd5\xa7\x0f\xaf\x74\xbc\x3c\x4c\xe6\x27\xaa\x63\x4e\x8e\xbb\x69\x9e\xad\xde\x25\xcd\x02\x9d\xab\xbe\xe2\x3f\xb7\xf0\xcf\x0c\xff\xc3\x5f\xff\x30\xc3\x9f\xf3\x2c\xcf\xc5\x9f\xb7\xab\x64\x9a\x35\x54\x58\x16\xcd\xeb\x64\x99\xe5\xf2\xc7\x07\xc4\xcb\xf0\x88\xdf\xcd\xb1\xf0\xa6\x4a\x66\x18\xef\x85\x96\x80\xd0\x87\x2e\xfb\x04\xa8\xbc\x86\xdf\x18\xb4\x20\xad\x5e\x15\x33\xf5\xfc\x26\xd3\xcf\x94\x36\x00\x7e\x95\x14\xf9\x1f\x1f\x54\xf7\xab\x04\xd5\xc4\x85\x70\x38\x95\xcd\x89\x52\xf5\xb3\xcc\x0a\x7e\x10\xf9\xd6\x9f\xa3\xa7\x47\xf3\x1e\xcd\x32\xa0\xb4\xc2\xff\x70\xb8\x15\xb6\x58\x43\xa5\x64\xc6\x2e\x3f\xf8\xb3\x29\x57\x2f\xca\xbc\xac\xc4\xb3\x9e\x39\xec\x41\xf9\x6b\xaa\x1e\x5e\x26\xf5\x42\x18\xc5\x89\x92\x9f\xb3\x22\x9d\x02\x3c\xca\xdf\xee\xa7\x7f\xce\x66\xb4\xe0\xe8\x3e\xf3\xbc\x98\x2e\xa8\x8f\xc6\x58\x25\x0c\x1a\x8a\x70\x0d\x4f\x59\xfa\xe5\x8f\x25\x8e\xf1\xeb\x18\xff\x39\xc3\x7f\xe0\xbf\x5b\xfc\x75\x8b\xbf\xa0\xd9\x0d\x26\x02\x52\xe1\x78\xc8\x10\xcd\xd8\xd8\x00\x9f\x4e\x61\x65\x16\x81\xb5\x85\x01\xfe\x38\x15\x2b\x1a\x98\xfb\x19\xe0\xf3\xe9\x9c\x7e\x04\x7a\x6f\xb9\xb8\x86\xc7\xc0\xb3\xb7\x41\xab\x28\x70\x76\x3b\xb0\x7e\x06\xc6\xde\x07\xfc\x78\x0a\x84\x6a\x60\x80\x81\x2c\x5e\x66\xaa\x98\x21\x42\xbe\xa0\xbc\x19\x81\x17\x16\x02\x4f\x61\x60\xc3\x47\x60\xfe\x0a\xbc\x30\x12\x78\x0a\x03\x1b\x52\x02\xf3\x57\x60\x80\x4d\x80\x8f\xa7\x53\x7c\x0e\x2c\x08\xe2\x17\x6a\xe1\x5d\x28\x0a\xb8\xe0\x74\x26\x4b\x02\x07\xac\x64\x85\x9c\x7f\x07\x0e\x94\xc9\xd7\x4e\x07\x0c\x74\xf2\xe5\x17\xfc\x15\x98\x10\x48\x09\x77\x4e\x13\xfa\x11\x28\xb8\x0b\xc4\x43\xe0\x4b\xde\xe9\xc4\x1f\x22\xc4\x75\x58\xaa\xdd\x8e\x2c\x33\xc7\xc7\xf5\xb6\x34\x3b\xc2\x50\xf6\x90\x44\x34\xd0\x11\xe7\xc2\xb3\x8c\xb4\x24\x3f\xe6\x79\xa5\xd3\x01\xf1\x92\x50\xec\x95\x74\xa8\x7f\x84\xfc\xc8\x49\x49\xd4\x1b\xfe\x19\xaa\xdc\x22\xf0\x42\x3d\x73\xa9\xfa\xc0\xf8\xb5\xd9\x78\x93\xaf\xec\x9d\x0d\x47\x8c\xd4\x4a\x89\x13\xb5\x52\xe4\x84\xec\xae\x37\xc4\x3f\x61\x83\x8e\x7d\x43\xca\x65\x47\x44\xd5\x2a\xcc\xd3\x79\x63\x14\xfd\x0c\x3f\x37\xae\x2e\x14\x86\x79\x2b\x4d\x36\x3e\xdf\xdf\x7f\x06\xd2\x7e\xda\x1f\xb4\xdc\x5b\x30\xaa\xfa\x67\x92\xea\x1c\xdd\xdc\xdf\x1f\x01\x1d\x46\x59\x26\x6e\xe2\xd4\x14\x45\x0b\x1a\x6a\x26\xa6\x15\x2e\x8d\xc4\xd9\x05\x27\xce\x16\xc0\x11\x84\xf0\x9b\x52\xf1\xc5\x9f\xc3\x64\x98\x4c\x61\x3d\xd6\x39\x3a\xc3\x8b\x54\x06\x2f\x45\x4e\x43\x4a\x7b\x14\x16\x96\xf6\x93\xcc\x8a\x5e\x94\xac\x82\x33\x0c\x08\x39\xb3\x18\xc0\x6f\x72\x83\x36\x19\xae\xee\xb3\xcb\x70\xf0\xc3\x6d\xd1\x2c\xd2\x26\x9b\xd2\xf7\x5a\x5e\xed\x49\x86\x25\xf5\x9d\xe4\x9c\x4c\xed\xe9\x77\x2b\xe5\x71\xf9\xd6\xc8\x1d\x07\x27\x3e\xcf\xcb\x2f\xaf\xfe\xb6\x4e\x72\x8a\x5a\x53\x5a\x09\x40\x6b\xb4\xac\xe3\x25\x89\xee\x56\x38\xf1\xd9\x7b\x0a\x70\x59\x69\x13\xe4\xe8\xee\x9a\xb3\x5e\x46\xab\xfe\x1d\x1c\x09\xae\xcd\x4e\x9a\xa1\x48\x3e\x69\xbd\x13\x19\x2c\x65\x24\x20\x60\x5b\x50\x60\x90\x02\x1d\x03\x8d\x5d\x2c\x70\x00\x7f\xcc\xd7\x55\x48\x4f\xc2\xe9\xf3\x4d\x5a\xac\xb9\xe0\x35\x42\x31\x3f\xfe\x6b\x7a\xfb\xb2\xfc\x52\xf0\x8f\x37\x25\x9c\x7a\xe7\xe7\xa7\x15\xff\xd0\xe7\x7a\x81\x00\x7c\x49\x16\x7c\x44\x09\x2e\xf9\xcf\x0d\xff\xb9\x45\x6e\xf5\x2a\xbe\x4b\x29\x15\x23\xce\x3f\x9a\x85\x56\x82\x61\x4f\x08\x5e\xe9\x13\xc1\xce\x10\x3d\x3d\xc8\xa8\x9f\x73\xfe\x5a\x99\x2f\x2c\x6d\xe5\x0b\x3b\x3e\xee\x7f\x8e\x53\x1c\x85\x18\xc2\x60\xc2\x19\x4e\x74\x53\xb8\x14\x91\x6f\xb4\xad\x9a\x6a\x05\xa2\x5b\x0c\x36\xe3\xbe\x36\x56\x32\x72\x3e\xfa\xb4\x12\x3e\x0d\x3d\x5a\x81\x0c\x73\x0f\xeb\x2a\xce\xea\x19\x1f\x8b\x0d\xb0\x4b\x74\x63\xd8\x8e\xed\x5f\x7c\x65\xe4\xe2\xd4\x27\x24\x7a\xf2\x43\xe8\x3b\x1f\xd1\xf7\x0f\x77\x99\xe4\x39\x87\x23\x1a\x3f\x92\xa1\xd3\xec\xb3\x81\x89\x95\x42\xff\xd1\x88\xc6\x3f\x92\x58\x93\x4f\x06\xfc\x7a\x1c\xba\x07\x03\xa8\x64\x32\x77\x7e\xb4\x5f\x92\x6d\x0a\x49\xb3\x2a\xbf\xf4\xcf\xc2\xc7\x0f\x07\x9d\xa6\x31\x6d\x1e\x9e\x3e\x9c\xa6\x59\xde\xa7\x27\xa0\x6b\x66\xe5\xb2\x3f\xf8\x43\xd5\xf6\x54\xa7\xe1\xec\xb2\x2e\x34\x88\xf6\x16\x52\x6a\xa7\xc5\xfc\xd4\x64\xb9\xa1\x3a\xf7\xa0\xab\xc4\xc1\x48\x2f\x80\xd0\xbb\x2e\x93\x6a\x26\x51\x53\xdd\x81\xb2\x5c\x54\x46\xe7\xc3\xc1\x67\xea\x25\xc0\x90\xd5\x68\xee\xbc\x27\x90\x95\x2f\x57\xce\xcb\x97\x55\x72\x23\xdf\xcd\x9d\x77\x1f\xcb\xb5\xc8\x42\xab\x93\x64\xaa\x97\x9f\x7e\x92\x6f\x66\xce\x9b\x3f\x2f\xd2\x34\x97\x2f\x75\xb2\x65\x5e\x51\xa0\x98\x5e\x70\x7c\x73\xaf\x8c\xcc\xc2\xb9\xb7\x2d\x91\x59\x65\x63\x5b\x94\x97\xdd\x5d\xe3\x81\xdf\x8d\x6c\x6f\x10\xa1\x12\x72\x38\x1a\x99\x88\x56\x95\x4b\x34\x8b\xaf\x37\x28\x99\xca\xa6\xbf\xee\xdb\xee\x0b\xaa\xec\x69\x98\x5e\xb8\x2d\x1b\x88\x65\xdf\xf6\x8d\x4f\x7c\xbd\xe8\xd7\xad\xbe\x56\xb7\xfb\x77\x02\x75\xbd\xad\xaf\x6e\xdd\x66\xd7\xfb\xdc\x6f\xfc\x35\x54\xf5\x35\xba\x6e\x9c\x36\x67\xe5\x1a\xbe\x7a\x71\xc8\xb2\xbf\x34\x3e\xf1\xf4\x61\xbc\x76\xfb\x02\xa8\xdf\xbb\x13\xac\xeb\x6b\x1d\xca\x3d\xcd\x22\xbb\x74\x40\xcb\x58\xbd\xa3\x71\x78\xe5\x6d\x1f\xb3\xbf\x1e\xd4\x03\x7e\xd0\xd9\x07\xc6\xde\xf6\xf4\xf2\x35\xdb\x7b\x87\x5f\xca\xfa\x5d\x7d\xc0\x3b\x4f\x17\x9c\x45\xeb\x80\x3e\xf8\x83\x8e\x4e\xe8\xa5\xa7\x97\xb7\x9f\x0f\x5b\x2d\xaa\xdf\xd1\x07\xbe\xf3\x74\xc1\x2c\xef\x01\x7d\xf0\x07\x1d\x9d\xd0\xcb\x56\x2f\xc0\x0c\xec\xdd\x01\xd4\xf5\xb6\x5d\xae\x9c\x66\x89\xc1\xd9\xb7\x5d\x26\xd1\x3c\x0d\xd3\x0b\xa7\xe5\x0c\x09\x86\x7d\x5b\x26\xea\xc2\xd7\x32\xbd\x70\x5a\xfe\x55\x90\x50\x7b\xb6\x2d\x29\x2e\x4f\xeb\xe2\x55\xbb\xfd\x77\x55\x5a\xef\xbd\x2c\xff\x2a\xeb\xfb\x7b\xa0\x77\xed\x2e\x3e\xed\xbd\x9d\x4c\x20\xfa\x1b\xff\xe4\x6e\x68\x5e\x26\x7b\x23\x9f\x9f\xb1\xae\xa7\x5d\x2c\x77\x9a\x4d\xd1\x11\x7b\xdf\x76\xc9\x6b\xdb\xd7\x30\xbd\x70\x5a\x5e\x2a\x12\x7c\xcf\xd6\x35\xcd\xee\xe9\x41\xbd\xf4\xf5\xf2\xa6\xdc\x1f\xdb\xbc\x51\x1f\x74\xf5\x82\x2f\x7d\xbd\xbc\xdd\x1f\xec\xdf\xc8\xfa\x5d\x7d\xbc\x6d\x01\x3f\x77\x71\x00\x46\x7b\xa3\x3e\xe8\xec\xa4\x8d\xd3\x96\x82\xc5\x39\xa4\x0f\x3f\x8c\x8a\x57\x4e\xfb\xab\xa4\x6e\xf6\xde\x8a\x77\x54\xd9\xd3\x36\xbd\x70\x5a\x66\xf7\xd0\x3d\x5b\x7e\x4f\x95\x3d\x2d\xd3\x0b\xa7\x65\x4e\x17\xb3\x6f\xd3\x9c\xac\xc5\xd7\x36\xbf\x71\x1b\x5f\x5f\x2f\xf7\xbf\x6e\x3f\x70\x6d\x5f\xe3\xf4\xc6\x69\xbc\x41\x22\xfe\x05\xaa\xf3\xf7\x1e\xfe\x47\xe3\x13\x4f\x37\xc6\x6b\x5f\x5f\x07\x10\x40\x1f\x65\xfd\xae\x5e\xda\x24\x10\x75\x71\xc8\x59\xfe\xa8\x3e\xe8\xea\xc4\x73\x96\xa9\x97\x83\xee\xf5\x8f\xfa\x8b\xae\x7e\x7c\x37\xfb\x17\xe4\x95\xf6\xed\x83\x18\x2b\x5f\xf3\xf4\xc2\x6e\x79\x13\x5e\xc7\x77\x52\x1c\x72\x35\x44\x26\x09\x45\x8a\x4c\x2b\x5f\x0d\x89\xbb\x09\x1d\x29\xc7\xd5\xd0\x60\x4d\xf8\x25\x70\x04\x58\xba\xba\xa5\x9f\x80\xac\xe0\xd7\x9a\x84\x93\x26\xed\x7d\x35\x34\x88\x77\x7a\x89\x34\x33\x94\xc2\x1f\xf9\x13\xb7\x99\x4b\xe0\x49\x17\x22\x6d\x2a\x8b\xe1\x59\xbd\x40\x7a\x52\x94\xc3\xa3\x2c\x66\x12\x90\xcb\xe9\x59\xbe\x20\x1c\xc7\xe5\xf8\x28\x8b\x79\x43\xb8\x9c\x65\xcf\xf4\x02\x28\x24\x2c\x2b\x57\xf8\x93\x2f\xac\xab\x21\xdd\x72\xa1\x12\x46\x5d\xb1\xfc\x17\x0b\x98\x40\xb9\x1a\x12\x55\x13\x1a\x72\x9c\xab\xa1\x20\x47\x44\x21\x53\x02\x54\x4a\x8f\xa1\x92\xf0\x50\xd9\x27\xea\x8f\x2e\xde\xab\x21\xde\xd5\xa1\x25\x85\xba\x1a\xaa\xeb\x50\xbd\x20\xc0\x15\x2f\xf0\x59\xbd\x78\x4b\x23\x92\x77\x8e\x2e\xe6\x75\x50\x17\x45\x68\x88\xac\x44\x31\x8f\x82\xf1\xea\xd5\x90\x90\x31\x16\x30\x3a\xbc\x62\xd3\x0c\x2c\x10\x48\xec\x4a\xa4\xca\xa2\x22\x46\x3d\x57\x43\xc6\x58\x58\x64\xe2\x8a\xab\xa1\x81\x6c\xd4\x4b\xde\x78\x89\x1a\x54\xb1\x98\x99\x3a\xcf\xea\x85\xdc\x33\x7d\x06\xf1\x15\xc3\xfe\xd5\x90\x0e\xcc\x46\x99\x5b\xbd\xc2\x38\x24\xd7\x83\xeb\x8b\x57\x97\x43\x53\x2e\x1a\x43\x01\x89\x73\xbe\x5a\xd2\xc9\xab\x30\xfd\x9a\x02\x00\x2b\x79\x74\x47\x40\xe8\x6c\xe8\xd4\x93\xd1\xc4\x2b\xca\xae\x4c\x29\x81\x50\x49\x24\xc5\x3d\xc2\x6a\x6e\xb8\xaa\xa8\xb3\x97\x1c\xf8\x84\xf2\x1c\xef\x12\x87\xb2\x47\xc6\x35\x46\x44\x40\x71\x7c\xd6\x92\xd5\xdf\x4c\x1c\x89\xe9\xed\x50\xc1\xa4\xfe\x4d\x50\xa5\x7f\x32\x50\xeb\xdf\xbc\xbb\xfa\xb7\xd8\xc9\x9b\xb8\x36\xe5\x9e\xb7\x43\x13\x8e\x45\xbe\xed\xcf\x46\xb2\x50\x1a\x94\x55\x55\xcb\x33\x6f\xb5\x3c\xf3\x26\x9e\xb6\x9a\x25\x44\xa4\x7f\xf2\x21\xbb\x89\xd7\xad\x8a\x8c\x52\xa0\xf3\x33\xe8\xbc\x1a\x5e\xaf\x9b\xa6\x2c\x3a\x06\xd0\x92\xd1\x52\xa9\x89\x9a\x74\xa9\x3e\x68\x4e\x19\x41\xa2\x53\xf6\xd6\x5a\x5c\x7d\xb4\x9c\x32\x9a\x6b\xde\x9a\x02\xa1\x3f\xfb\x27\x9e\x02\xb7\xa4\xb1\x1a\x54\x68\xcf\x2e\x62\x94\x67\x97\x39\x43\xd1\x98\xce\x2c\x2b\x71\x6c\xab\xd6\xd8\xcc\x03\xeb\x94\xda\x63\xd4\xa7\xd4\x29\xe3\xae\x6e\xe2\x79\xab\x6d\x81\x32\x6e\xe2\x45\xeb\x15\x9f\xdf\x9b\x78\xd6\xde\x6f\xbc\x64\x8c\x9f\xd6\xca\x33\x9a\xba\x89\x93\xcd\xb2\x7f\xc3\xa6\x37\x57\xf1\x8d\xa1\x9c\xca\xe8\x14\xa9\xe4\xbb\xdb\x55\x4f\x57\x83\xf0\xca\x92\x0c\x7f\xdd\x2d\x5f\x37\x44\xbd\xd1\xf7\x67\xdb\xe4\xee\x5d\x62\xde\x68\xfc\xe8\x49\xe8\x97\xb9\xc2\xab\x1f\xb6\x88\xe5\x7d\xf2\xdf\x68\xfc\x78\x14\x76\x8b\x7f\xe1\xf5\x59\xd8\x21\xfd\x85\x77\xf6\x40\x0d\x01\x2f\xbc\x7b\x14\xfa\xe4\xbb\xf0\xe2\x71\xd8\x21\xde\x85\x77\x4f\x42\x9f\x74\x37\x1a\x7f\xff\xc4\x6f\x48\x63\x6b\x0d\x5a\x66\x35\x87\x7b\x57\x67\xa6\x31\x1b\x1b\xa4\x19\x4e\x6e\x2d\xc9\x7a\x19\x93\xe1\x05\xad\xd8\xcb\xa4\x49\x3c\xa1\x7f\x03\xab\x02\xe9\xbb\xcf\x9b\xa1\xfd\x95\x50\x48\x5b\x85\x00\x59\xd9\x30\x59\x53\x28\x22\xb2\x52\xea\x57\xe8\xe2\xde\xf2\x7b\xf2\x6c\x36\xcd\xfd\x90\x30\xdb\xdf\x3a\x77\xcc\xc3\x2d\x32\x7e\xff\xa6\xb1\x1e\xe2\x81\x7c\xd0\x58\x2d\x65\x85\x18\x30\x1b\xac\x00\xca\xfb\x96\x81\x3b\xf0\x4f\xa3\x3f\x3c\x40\xb1\x30\x0a\x65\x4c\x02\x98\x62\x9e\xdd\x48\xc7\x4c\x59\xfa\x86\x4c\x5e\xe2\x94\x4b\x8b\x84\xd4\x69\xd8\x6f\x5c\x48\xc5\x12\xd9\x86\xca\xa4\x88\x65\x35\x24\x87\x86\x79\x32\x4d\x15\x3d\x93\x75\xe7\x1f\xc9\x54\x1c\xce\x0a\x03\xe5\x61\x63\xf0\x37\x2e\xcf\xcb\x7e\x31\x88\x0a\x78\x16\x21\x09\x85\x0b\xfc\x50\x84\x5f\x7b\xc7\x34\x49\x3a\x3b\x6f\x17\x45\x68\x7c\x8a\x30\x4f\x11\x96\x88\xb6\xe1\xcc\x1e\x59\xfd\xd2\xa9\x1a\xd7\xe7\x89\x19\x31\xf6\x63\xb5\x4e\x23\xab\xe4\x75\x92\xd7\x62\xf6\x59\x6d\x50\x46\x1f\x00\x8f\xaf\xa0\x81\x76\xe5\x9d\xee\xa8\xae\x5d\x75\xe2\xf7\x21\xad\x6d\x25\xd3\x47\xb2\x44\x20\x35\xda\x1d\x25\xe2\x61\xdb\x51\x2a\x8d\xea\x50\x38\xa6\x70\x2d\x7b\x0a\xbf\x50\x9e\x67\xc2\xef\x78\x75\x08\xeb\x47\xe2\xc1\x6a\x11\x59\x99\x6e\x4e\x54\x46\x8b\x56\xb3\x25\xba\x29\x2d\x57\x1e\x44\x82\x61\xee\xe5\xeb\xfb\x7b\x8c\x32\x37\x2c\xca\x2f\x7d\x52\xe1\xbb\xfb\x40\x6e\xff\xb8\xa8\xb5\xfc\xb9\x99\x94\x76\xd8\x2f\x9b\xb8\x6c\x9b\x2c\xbb\x1b\x76\x34\x9a\x18\xe9\x30\x0c\x80\x9c\xb8\x84\xea\x79\x9b\x72\x8d\x1a\x0b\x32\x64\x44\x29\x0f\x5c\xb4\xa0\x62\x13\x3a\xa4\x71\x47\x82\x0e\x7b\x44\xce\x37\xe7\x1e\x02\x3b\x42\x07\x06\x5c\xfe\x3f\xd2\x8e\xa0\x63\xd8\x9e\xd0\xc6\xc3\x42\x4b\x70\x60\xb0\x5b\x2b\x07\xdf\xf3\x1b\x3c\xac\x9e\xef\xcc\xf7\x3e\x90\xf7\xdb\x91\x1b\x33\xdd\x7e\xe6\x45\x2c\x45\x3a\xd0\x98\xea\x00\x49\x5c\x1f\xbe\xd1\x9e\x37\x0e\xca\xd1\x2f\x2c\xac\x43\x1e\xba\xa8\x33\x55\x5d\xc6\x6b\xf8\x65\x22\x4f\x6f\x20\x0d\x42\xd1\x55\x2c\xce\x1e\xab\xe2\xfb\x85\x86\xc4\x01\x02\x26\x27\x58\x10\x05\xe6\x8f\xd8\x7a\x65\x4e\x1d\x11\xa6\x31\x96\x12\x7d\xda\x0a\x5d\x10\x52\x3b\xd6\xe8\x0a\xeb\xa7\xeb\x53\xdc\x40\x41\xb3\xa8\xd2\xf4\x79\x75\x43\xe6\x57\x84\x42\x30\xd4\x87\xeb\x7c\xdc\x51\xf1\xdb\xe3\xbc\xb5\x7d\x89\xc3\x36\xfe\x01\x22\x88\x2e\xcb\xc7\x87\xb8\x18\x1f\x74\x59\x6a\x1d\x7c\x89\xb1\x17\x90\xea\x9d\x09\xb4\xf6\x2d\x57\xa5\x49\xf2\xd1\xc0\x0f\xf0\x40\xfb\xbf\x4d\x91\x3c\x3e\x24\x74\xfd\x37\x2f\x72\x97\x2d\x43\x62\xbf\x01\x92\xbc\x7d\x2b\xbd\x29\x67\x18\xc2\xbe\x12\x8e\xa9\x78\x39\x01\x31\x1c\x25\x61\x2e\x02\x54\x8a\x0b\xa6\xa9\x72\x0c\xc9\x48\x3f\xea\x45\x36\x6f\xd4\xaf\x24\xd7\xcf\xcb\xb4\x49\xd4\x8f\x2a\x5d\xc1\x21\xe5\x67\x6c\x4d\x5e\x4e\xd0\xb5\xd5\x2b\x5e\x7e\x62\xd0\x3e\xba\x17\x86\x83\xe6\xb4\x75\x40\xf9\x20\xf0\xf8\x9e\x63\xd2\x94\x68\x44\x3a\xab\x2d\x5f\x01\x29\x5c\xe8\x8f\xee\xef\xb1\x6c\xbd\x32\x9a\x69\x86\xb2\x81\x11\xca\x3c\x33\x4b\xf0\xb2\xb3\xff\x83\xbb\xf0\x80\xd2\x7a\x5f\xc0\xdf\xca\xcf\x98\x1b\x0c\x65\xdf\x87\x9d\xfb\x0b\x6f\x89\xa3\x79\x7c\x88\xbd\xed\x6f\x83\xcb\x7f\xcb\xd2\x2f\x38\xbf\x37\x29\x36\x5d\xb7\xc1\xd2\x85\xc0\x3a\xbe\xab\x01\xbd\xa7\xc5\xbf\x0b\x68\xa3\x1f\x7f\x11\x70\x48\xa9\x60\xff\xdd\xfc\xf1\x97\x6f\x87\xd0\x16\x24\x26\x21\x0b\x76\x3c\x6e\xe9\x8d\x90\xf9\x08\xa6\x3e\x20\x78\x61\x36\x2c\x8d\x50\x28\x94\x9e\x9f\x45\x8f\xe8\xef\x18\xe1\x89\x6b\xd7\xf2\x28\x98\x58\xd0\x4b\x93\x59\x55\xee\xef\xfb\xcd\x10\x53\x2f\x4a\xdf\x61\x04\xa8\xba\x9a\x8a\x9f\x00\x56\x4d\x29\x0d\x76\xad\x8a\x18\x24\x35\xb9\x49\xff\xdd\x07\xc8\xf4\x42\x32\x8e\x5c\x8b\x18\x48\x5c\xd0\x13\x15\x9c\x80\xa5\x25\x64\xc6\x4b\x4d\xfd\xa5\xab\xa9\xbf\x98\x4d\xfd\x45\x35\xf5\x17\xb7\xa9\x8f\xe5\xca\x07\xfa\xf5\x21\xa0\xef\x02\x11\x94\xff\xb0\x07\x94\x1f\x10\xd7\xf4\x77\xc2\xbe\x2e\x30\x27\xa8\xee\x58\xa3\x98\xc7\x24\xf7\x3f\x9a\x45\x53\xb2\xc7\x9c\x59\x65\x9d\x10\xbb\x05\xca\x5b\xc0\x5c\x7a\x56\x3d\xf9\x16\x84\xd3\xb1\xba\x87\x67\x8d\x3d\xf8\x1e\xf6\x33\x50\xb0\xa8\xe8\x5f\xe0\xa6\x49\x6f\x86\x58\xaa\x23\x8c\xe3\x2f\x61\x57\x5e\x8a\x88\xdb\xcc\x84\x52\x82\x73\x96\x95\x50\xe8\x6d\x95\xc0\x5c\x86\x6c\xa3\xe0\x6c\x2f\x85\xf9\xbc\x11\xf7\x44\x72\x33\x08\x8e\x18\x4d\x80\x2d\xe5\xff\x4c\x2d\x09\xe1\x0b\x72\x51\x4d\x92\xe5\xfe\x43\xce\xef\xee\xef\xbd\x97\xc1\xd6\xbd\x69\x59\xc6\x7a\x69\xba\xbf\x9b\xa0\xaa\x25\x00\x49\xf3\x26\xf1\x62\x19\x7e\x23\x71\x83\xa8\x17\x90\x82\xe4\xa5\xf1\xea\xb4\x19\x1a\x65\x11\x85\x45\x86\x27\x2f\xb6\xe1\x37\x56\x93\x7f\x31\x9b\xfc\x8b\xa7\x49\xab\x82\xe7\xbd\xea\xf1\x7f\xf2\xe9\xa1\xe7\x37\x32\x53\xee\xef\x20\xce\x79\xbc\x5f\xd0\x3e\x5f\x12\xb0\x8e\x08\x08\x2d\x0e\xb1\x69\xbb\x14\x33\x67\xe7\x77\x37\x96\x01\x10\xbe\xf0\xef\x9f\xa0\x0f\x14\x10\x9e\xfb\x0a\x95\x0b\x75\xe4\x7b\x8b\xf9\x69\x39\xa8\x69\x56\xff\x54\x98\x6e\xa3\x47\xe3\x4d\xe8\x16\x62\xa6\xac\x0e\x07\x68\x21\x60\xb0\xab\xb7\x2c\xaa\x8f\x8e\xbc\x9d\x75\xf9\x17\x63\xcc\x85\x30\x09\x6b\xa0\xae\xee\xaa\xfe\x91\x60\xa6\xad\x4f\xfb\x22\x12\xdf\x34\xcc\x8d\x74\xae\xad\xc9\x8c\xc2\xa9\x66\xe7\xd5\x96\xa0\xcf\xee\x88\x0c\x9a\xf9\xec\xd8\x5d\xe2\x27\x3a\xfd\x2b\x36\x4e\xa9\x1b\x54\x2f\xe4\x5b\xce\x4d\x6c\xa6\xa4\xc4\x5b\x0d\xee\x36\x29\x70\xec\xbd\xd6\x7b\xd5\x4a\xd7\x5a\xcb\x60\xff\x39\x1a\xb7\x19\xe3\xb3\x93\xf1\x49\x8e\x3e\xee\x82\x9a\x10\xd8\xeb\x49\xf1\x34\x95\x61\x19\x8c\x30\x11\x94\x52\x49\x0d\xde\x81\x03\x78\x17\x97\xc3\xb7\x7f\xfc\xf0\xea\xfd\xbf\xbd\x7a\x79\xf5\xea\xfd\xfb\xb7\xef\xbd\x30\x86\x15\x2b\x63\x09\xcf\xcd\x1f\x1a\x03\x89\x98\x45\x72\xda\x32\x9b\xad\xa7\xb1\xb8\xd5\xaf\x5e\x61\x7b\xa7\x8a\x93\xb1\x5c\xe8\x0c\x16\x7a\xb3\x11\xee\xfd\xee\x2a\x89\x54\xa7\x1e\x40\xf9\x0d\xeb\x97\xc1\x5d\x45\x39\x46\xc4\xc1\x6c\xcf\x84\xd6\x36\x43\x28\xab\x8f\xda\x93\x3a\x3e\x4e\x18\x20\xd4\x83\x81\xae\x6b\x44\x16\x06\xac\x61\x8a\x33\x0f\x9c\x19\x0b\xb0\xa6\x05\xd8\x7a\xde\x61\x79\x4a\x99\xe6\x3a\x0b\xed\xd1\x44\x77\x3e\x77\xbe\x76\x0c\xc2\xc7\xfb\xe5\x3f\xbc\x6b\x51\x9c\xd1\x28\x74\x49\x47\x28\xaa\xd2\x39\xf0\x5f\x0b\x2e\x22\xc1\x9f\x9d\x44\xb2\x6a\x93\xae\x70\x34\xbf\x86\x55\x8b\x0e\x85\xe2\xdb\x8d\x2f\xdb\xdd\xe3\xc3\x64\xef\x9c\x4e\x4e\x52\x13\x03\x91\x52\xae\x71\x09\x09\x37\x67\x48\x58\x39\x45\xa9\x19\x22\xac\x3a\xef\x73\x36\x84\x21\xec\x4c\x7e\xcb\xa1\x45\x80\xcf\x2c\x64\x79\x9f\x7f\x57\xe7\x17\xcd\x25\x4a\xb0\x60\x4f\x31\xe4\xd6\x05\x54\xb4\xd2\x3b\xf8\xa3\x60\x56\x5d\xbb\xf5\xe4\xb0\x58\x73\xfa\x34\x8c\x01\xec\x61\x77\xe2\xd1\xa4\xd2\xf9\x8a\x2a\x00\xfd\x34\xee\xa7\x27\x80\x1c\x05\x9f\xfa\xbc\x41\x5d\xfd\x3f\x65\x50\x1d\x80\x31\x85\x27\x15\xdf\xf4\xbe\x78\xfa\x74\xfc\x44\x0c\xfe\xc9\xe3\xc7\x67\x63\xcf\xe6\x3c\xf1\x08\x7c\xec\x31\x19\x4c\x14\x85\x6c\xea\x67\x61\x47\x44\xdf\xa6\xfc\x84\x60\xff\x02\x63\x2d\x0c\x36\x92\xd6\x79\x70\xda\x1f\x0e\x1e\xdc\xf8\xfa\x3e\x2c\xf7\xa0\x72\x99\xd2\x43\x29\xc3\x60\x59\x9f\x62\x76\x1f\x63\x8b\xa6\xc9\x32\x45\x04\x45\xc4\xd4\x83\xff\x75\x0a\x35\x1e\xb4\xf7\x4a\xd5\x8a\x60\x0d\x68\x34\x1e\xb6\xdd\x85\x4c\xb9\x16\x40\xe3\x9e\x37\xc4\x8e\x1e\x8d\x22\xf4\xc2\x3c\x3f\x1a\xc3\xdf\x74\x70\x4e\x15\x05\xed\x8a\x0e\xa6\x24\xc1\x2e\x0b\xa0\x4c\x0b\x0c\xee\x26\x1f\xfb\xe2\xc5\x12\x6b\x4a\x62\xf8\x5d\x59\x67\x24\x08\x3f\x3a\xea\x8f\x9f\x1c\x77\xbe\xc7\x98\x6c\x70\xef\xc3\xff\x2d\xc8\x24\xbf\xad\x5f\x48\x3a\xe5\x01\x4d\xfd\x36\x1a\xff\x48\x44\xd4\x13\x0f\x07\xe7\x5b\x71\xa0\x10\x8e\x8f\x8d\x7c\x3a\x32\xbc\x84\x99\x0b\x55\x97\x0e\x8e\x8f\x03\x06\x57\xe1\x36\x7c\x84\xee\xc4\x1c\xc8\xeb\x73\x92\x53\x21\xd6\x11\x39\x67\x8c\x24\xaa\x98\x2d\x06\x6d\x76\xa0\x33\xf7\x70\x43\x57\x88\x9a\xd3\x94\x3e\x87\x5f\x59\x93\x2e\xb9\x29\x7f\x76\x60\x1c\xfe\x79\x2b\xad\x10\xb0\xf9\x14\xe7\x66\x10\x91\x90\x09\x8e\xba\xe9\x94\xda\x94\xcf\x39\x7d\x4e\x3b\x6f\xa6\x7c\x15\x9d\x8d\x28\x24\xf8\x93\x43\xd8\x33\x29\xe4\x28\x85\x60\xfd\x75\x82\xa2\x71\xc2\x59\x45\x2c\xe3\x45\x33\x25\x7c\xd7\x24\x37\x94\xec\xba\xb1\x0f\x53\x88\xe2\xff\x3c\xe1\x44\xd8\x1c\xb4\xe4\x35\xa0\xc5\x77\xc9\x8d\x0e\xf4\x1d\x9c\x34\xe1\x54\xfe\xf8\x73\x96\xe7\x22\x74\xa4\x49\xf2\x25\x18\xc7\x79\x23\x42\xf4\x7a\xbc\xeb\x64\x44\x50\xce\xa3\xbc\xd1\x18\xb4\x15\x50\xdf\x97\xe0\xa6\x15\xce\x78\x2b\xb2\x34\x9a\x89\x7e\xd0\x39\x7c\xdc\xd0\x6b\x1e\x9c\xea\x61\xc4\x7c\xeb\xdd\x0c\x97\x74\x31\xeb\xa0\xcd\xc8\x9b\x5e\x8c\x2f\x61\x6d\x7f\x2e\xbf\x28\x44\xe5\x06\xeb\xe4\xfb\x65\x3a\x59\xf7\x8f\x8e\xa6\x4c\xca\x62\xe2\x55\x0c\xda\x1f\x67\xc7\xc7\x75\x9f\x53\x83\x95\x83\xbb\x02\xc8\x21\x60\x66\xff\xf4\xf1\xcd\xcf\x71\x09\x0d\x9f\x34\x27\xe5\xc5\xd9\xa5\x22\x6a\x72\x28\x1d\x5d\x4e\xf2\xd3\xd3\xc9\xa0\x88\x8b\x21\x4c\x96\x13\x8f\x33\x49\x6a\x7e\xde\x50\x3f\xab\x98\x22\xa2\x89\x35\xa8\xff\x78\xfb\x91\xe1\x01\x8e\xd0\xb4\xca\x56\xb8\x8e\x2b\x71\x19\xc0\x29\x59\xe3\xa5\x95\x00\x89\x3b\x84\x0e\x5f\x25\x53\xbc\xc4\x34\x45\x35\x8f\x93\x7e\x31\xa4\xb4\xb0\x78\xec\x6b\x0c\x21\xa8\x06\x00\xe3\xb1\xb2\xa7\x1b\xaf\xd4\x6a\xcd\x2d\x8f\x6d\x32\x8e\xcb\xd0\x75\x5f\xe7\x44\x57\x1b\xcd\x30\x4c\x67\x04\x43\xcd\x03\x85\x93\xce\x2c\x71\x38\x07\x36\x46\x92\xae\x2b\x85\x76\x89\x8a\xbe\x4f\x75\xfa\xf2\xed\x9b\x73\xe5\x5c\xcf\xed\x4a\x6f\xf9\x60\x96\x7d\x0e\x06\x42\xe6\x0d\x98\xfd\xaf\xf5\x1f\x9e\xf6\xff\xfa\xe5\x64\xf0\xa0\x7d\x62\xbd\xe3\x8d\xbe\x27\x83\x17\xef\x68\xe1\x1a\x78\x14\xb6\x06\x0b\x30\xd7\x05\x85\x87\xd9\x6e\x48\xb0\x12\xa9\x15\x00\x85\xb5\xe2\xf5\x60\x21\xf9\x40\x73\xe8\x45\xc1\x9f\x4b\x82\x2e\xab\x7f\x49\x7e\x31\x88\x9a\xea\xfe\x1e\x4d\xf5\xe0\xa3\x56\x6e\x45\xc4\xaf\x25\x20\xb7\xf3\x20\x38\x49\x23\x95\xb8\x4b\x77\x84\x11\x3f\x63\xb8\xaf\xab\x6c\x09\x34\x78\x98\x9e\x04\xab\xaf\x81\x9d\xf5\xe7\xc3\x07\x23\x80\x0d\xc0\x3d\xa0\x51\x8c\xc9\x91\xa7\x75\xfd\x0b\x61\xee\xf6\x81\x36\xbf\x89\x38\xb9\xc7\x13\x0f\xb1\xea\xbd\xd4\x3d\xb1\x90\x37\x76\xf8\xc2\x4d\x66\x6a\x61\x63\x56\xf0\xd9\x5a\x59\x38\xa4\x18\xa6\x3e\x73\xd5\xb9\x58\x3e\x72\xca\x51\xed\x0f\xe5\x22\x66\xbd\xf5\x05\x60\xc0\xd8\x33\x1e\x28\xde\xd8\x35\xa5\x6e\x31\xb6\x08\x66\x39\xfc\xb0\xed\x8d\xfc\x64\x17\x25\x2c\x68\x77\x1f\x15\xfd\xfd\x61\x94\xa4\xb4\x8e\xc3\x3b\xce\x77\x43\xf6\x01\x36\x9a\x81\x22\xa4\x92\xb0\x92\x99\x21\xee\x82\xe3\x20\x0a\x8e\x93\xe5\x6a\x12\x84\xc1\x33\x7c\xbe\x69\xf0\xf1\x29\x3e\xe6\xf8\xf8\x5d\xf0\x1d\x3c\xfe\x6d\x5d\x52\xf9\x77\x58\xfe\x8f\x5f\xcf\xbe\x9f\x04\x1b\x40\x08\x0f\x2e\x8e\x9f\x3d\x0d\xbe\xbb\xb4\x48\x3e\xb9\x02\xdf\x1f\xa2\x5f\xd4\xa9\xbb\x99\x05\xe0\xc8\xc7\x35\xdd\xe4\x51\x86\x50\x8f\x8f\x14\x15\x1d\x31\x1c\x9e\x65\x15\xc7\x10\xae\xf7\x7e\x22\xa2\x2e\x37\x22\xca\x7a\x47\xf2\x76\x7e\x39\xe0\xe8\xbe\x74\x43\x0e\x36\xc2\x46\x77\x9f\x28\x82\x56\xa4\x64\xfb\x42\xa4\x48\xc4\xde\xeb\x50\xa2\xc6\xac\x16\x04\x9b\xed\xf5\xbc\xe9\xb8\x2d\xbb\xc2\x5e\x75\x86\x26\xe5\x11\x40\xd1\x23\xbf\x6d\x9e\xe8\x1f\x48\xc2\xb1\xcf\x38\xef\xfb\xc3\x55\xac\x42\xf2\x86\xdc\x73\xcb\x9e\xa9\x80\x8b\xf3\xf8\x58\xc9\x89\xfb\x15\x4a\x1b\x52\x97\x84\x53\x39\x2b\x15\xcf\xd7\x08\x49\x33\x1c\x0c\x09\xd7\xd0\x5d\x85\x3c\x5c\xba\xb9\x33\x49\xb8\x2a\xc1\x38\x4d\xc8\x9a\xd3\x5d\x06\xab\xb5\x6d\x6d\x25\x75\xe7\xf9\x0a\x56\xe0\x7b\xef\x8a\x1c\x16\x4c\x87\x24\x06\xec\x56\xd0\x97\x82\x82\x14\x05\x05\x9e\x03\xbe\x5f\xe4\x04\xb7\x8a\x87\xc8\x55\xd4\x00\xbc\x8f\x90\x57\x61\xb9\x46\x81\x41\x38\x7d\x98\xc5\x43\xcc\x5a\x81\x66\x71\x12\x32\xaa\xa0\xbc\x99\x13\x33\x76\xc4\xfd\xbd\x2a\xbf\x2e\x67\xb7\x62\x9e\xfa\xfc\xda\x6f\x7d\x73\x3f\x44\xb6\x2e\xe8\x3b\x94\x0b\x49\x05\xb0\xd4\x1b\x4a\xae\x98\x65\xd2\x7d\xa4\x01\x65\x51\x48\xb7\xe5\xf1\xf1\xf8\x21\xfc\x2d\xe8\x06\x1c\x3f\x04\x3e\x2a\x8d\x8b\x30\x7d\x16\x3f\x3c\xbb\xbf\xa7\x57\xe9\x39\xaa\x93\x3d\x43\x3c\xe4\xbe\x17\x2a\x13\x18\x9d\x22\xfe\x2f\xe8\xe7\xe5\xfd\x3d\xfd\xa5\x0c\xa5\x70\xa1\xce\x60\x55\x28\xcb\x3d\xa6\xc5\xd5\xca\x12\x8c\x3d\xe4\xd1\x8d\x1b\xe1\x9a\x15\x1d\xc0\xf3\x39\x0f\xc8\xb6\x3c\x88\x38\x0d\x07\x69\x2d\xa5\x2a\x1b\xe3\x2a\x1f\xa0\xb8\x4f\x2e\xd4\xb2\xc2\x68\xed\x41\x46\x41\x60\x52\x09\x1e\xb3\x08\xb8\x3f\x5e\xd5\xd3\x28\x80\x7f\x92\x55\x1a\x84\x1f\x56\x70\xbd\x5c\x27\x55\x14\xf4\x82\x90\xc4\x50\x01\x40\x6a\xf9\x05\x1f\x83\xf0\xd3\x4a\xfc\xfc\xb4\x0a\xc2\xf7\xd9\xcd\x42\xbe\xa6\xe7\x20\x24\xdb\x7d\x2e\xc1\x47\x28\x48\xf3\x28\x80\x7f\xd2\x06\xda\xfe\x73\x06\x2f\xdf\x7e\x08\x42\x72\x06\x08\x0c\xcf\x80\x20\x7c\xbe\x5a\xd5\x4e\x91\x30\x55\x0f\x84\x24\xab\x9c\xfe\x0a\x5f\x96\xff\xf5\x0e\x16\x8c\x42\xcd\xa0\xb2\xcf\x9e\x2e\x5e\x67\x77\x3f\x44\xc1\x1f\x31\x44\x2f\x4e\x24\x08\x7f\x8c\x82\x8f\xc9\x75\x10\x8e\xcf\xa0\x75\xa0\xdf\x2a\x78\x7c\x18\x89\xd5\x87\x1b\x1e\x9a\x47\xc5\x21\x3c\x7e\xcf\xdd\x43\x5f\xf0\x03\x1a\x79\x9e\x63\x29\x7c\xff\x2e\x01\xb0\x09\xc2\xb3\x11\x54\x48\x56\x35\x0f\xe4\xec\x7b\xbd\x66\x0f\xcf\x68\xb5\x1e\x3e\xc4\xba\x37\x29\xae\xcd\xc3\x47\xfc\xcc\xab\xf0\xf0\x31\xf6\x38\x83\x07\xe8\xef\x4f\xe5\x12\xbf\xf9\xde\x5a\xd8\x87\x3f\x18\x0b\xfb\xf0\x47\x7b\x55\x1f\x8d\xac\x35\x7d\x04\xad\xc1\x05\x92\x62\xd8\xb6\x47\x4f\xf4\xf2\x8e\x71\x8e\xaf\xc7\xf8\x00\x23\x79\x7d\x86\x0f\x30\x8c\xd7\x0f\xf1\x01\xbe\x79\xfd\x08\x1f\xe0\x83\xd7\x8f\xf1\x01\x06\xf0\xfa\x09\x3e\x40\xd7\xaf\xbf\xc7\x07\xe8\xf6\xf5\x0f\xb8\x54\xd0\xdf\xeb\x1f\xf1\x61\x8c\x0d\x8e\xf0\x89\x9a\xc6\xb6\xcf\xb0\xed\x31\x36\xfe\x08\x1a\x07\xda\x92\xd7\x03\x23\xb7\x58\x3b\x75\x76\x06\xaf\xdf\xa4\x4d\x12\xb8\x38\xac\xcb\x7a\x83\x4e\xed\x61\x79\x93\xb4\x24\x3a\x44\x55\xa5\x69\xae\x88\xb7\xd2\xd0\x55\x03\x2b\x1f\x95\xd6\x9b\xbe\x48\xf1\x50\xe1\xc9\x57\x39\xae\xab\xf3\xa3\xa3\xe2\xa2\xba\x44\xd1\x8d\x5f\x6e\x21\x89\x30\x80\x96\x28\x60\x4d\x75\x10\x0a\x38\x8a\x02\xa1\xa1\x46\x88\x6f\x92\x28\x10\xda\x6b\x00\x6d\x84\xb9\x28\x90\x3a\xeb\xc0\x17\x0a\xe7\xfb\xc3\x92\xd7\x48\x1e\xba\x11\x36\x13\xa6\x89\xc4\xfd\x3d\xeb\x63\xe5\xb4\x08\x6f\x2a\xf9\xcd\xb9\x29\xff\x8a\x52\x0f\x2e\xfd\xe1\x30\x5a\x56\x0c\x05\x70\x36\x50\x0f\xcd\x45\x86\x48\xf4\xa2\xbc\x94\x28\xd0\x97\x5c\x01\x90\x38\x91\x73\x23\x81\xae\x3c\x75\x3e\xdc\x2e\xaf\xcb\xfc\xf8\x98\xff\x0e\x33\x38\xc0\xe8\xdb\x01\x18\x2c\xf8\xe7\x7f\x96\xbf\x02\xcf\x7d\xf9\xc3\xbe\x22\xd3\xb2\x7f\x74\x94\x0c\xc2\x79\x9b\x3f\x43\x13\x94\x38\xf8\x03\xd2\x81\xde\x97\x89\x21\x19\x80\x6a\x88\x9c\xcf\x83\xa7\x79\x56\xfc\xda\x7b\x80\x14\xf9\x53\x20\xde\x4f\x82\x67\x4f\x1f\xf0\xdf\x20\xac\x01\xc8\xe2\xa3\x64\x38\xcf\x2a\xc9\xc6\x53\xd9\xf9\x1c\xfe\xd1\xa9\x42\xb2\xad\xcc\x7c\xd9\x26\x53\x13\x14\x50\x1d\xc2\x97\xd7\xf1\xdd\x34\xab\xa6\x39\x3a\xa5\x86\x2a\xde\x25\x3c\xcf\xd2\x39\x46\x4c\x08\xd3\x1c\x0a\x6b\x7a\x8d\x31\x56\x42\x8c\x98\x28\xff\x26\xd5\xff\x10\xe1\x28\xb1\x64\x25\xbe\x5c\x95\xf9\xed\x0d\x6a\x3a\xf9\x51\x7e\x80\x35\x93\xdc\xfc\xa0\xc2\xa8\x6a\xa8\xec\x69\x28\x1e\x06\xc7\xd6\x3b\x1a\x6d\xc2\x75\x7c\x31\x0e\xbf\x7b\xca\x51\xda\x7a\xcb\x75\xde\x64\xab\x3c\x8d\x39\xea\xd8\xb3\xef\x80\xb5\x79\xc0\xef\x9e\x05\x97\xe1\x14\x2b\x07\x4f\xe9\x4a\x78\x86\x6c\xcf\x03\xf1\x78\x19\xe6\xf1\xc5\x43\xf5\xea\x69\x83\xd4\x0c\xfc\xa9\x44\xad\x0a\xf6\x43\x94\xe9\x4f\x56\xdc\x5a\xfd\xf9\x86\x6b\xd1\xc3\x25\x26\x99\x85\x7d\x8d\xf0\xdd\xf9\x53\x58\x3e\x7e\x49\x0f\x97\x21\x1c\x9e\x84\x5e\x3d\x5d\x26\x2b\x7e\x43\x0f\x30\x36\x40\x02\x17\x67\xad\x21\xc8\x6e\xe1\xf5\x4d\x55\xae\xc5\x37\xea\x97\x39\x83\xf4\x06\x43\x31\x52\xe3\x80\xab\xf2\x59\x9d\x36\x5c\x5b\xff\x82\x41\x27\x55\xb2\xe4\x4a\x2c\xf5\xe5\x2a\xf2\xf9\x32\x6c\x2a\xcf\x30\x78\x15\xdc\x05\x28\x57\x0d\x8d\x22\x5a\xe3\x23\xaa\xa0\xd7\xe4\xca\x8c\x4f\xd3\x50\x8e\x11\x1e\xe9\x4b\xfc\x3b\x2f\xcb\x06\xff\x2e\x52\xf4\x6f\x0c\x9b\x59\x84\xa6\xce\xf0\x8f\x00\xac\x95\x86\xab\x15\x83\xd5\x4a\x41\xd5\x0a\x80\x6a\xc5\x30\xb5\x72\x41\x6a\xc5\x10\xb5\x52\x00\xb5\xd2\xf0\xb4\x72\xc1\x69\xc5\xd0\xb4\x62\x60\x5a\x31\x2c\xad\x3c\x57\xcf\x36\x41\x53\x5b\x6a\xf4\xc3\x61\x2a\x0f\x8a\xa0\x0d\x88\xaf\x31\x0e\xf6\x64\x80\x1a\x38\xe3\xb7\x92\x38\xd8\x37\x0a\x7f\x3b\x11\xa4\x68\x01\xe3\xff\x90\x5d\xa3\x79\xb4\x36\xe2\x31\x0a\x27\xd8\xa8\x46\xdb\x1b\x27\x19\x83\x56\x4d\x15\x52\x14\x3a\x02\xe4\x30\x9a\x14\xdc\x01\x11\xa1\xea\x06\xa0\xa2\x24\x2e\x4f\x38\xb0\xa5\x88\xf7\x2a\x04\x97\x48\x6d\x97\xc7\xc7\xc9\x33\x45\xef\xde\x51\x9e\xf8\x42\x86\x14\x4e\x4f\xcb\xcd\xa4\x8c\x93\x0d\x76\x95\x51\x1a\x98\x8d\xad\x18\xa5\x95\x3c\x8c\x11\x93\x73\x3e\xd7\x7a\x06\x18\x72\x86\x26\x2f\x02\xa9\x19\x26\x7f\x6a\x6d\x4d\xcc\xf9\xa3\xef\x2a\x38\x28\xb9\xb7\x50\xa7\x94\x98\x2f\x55\x21\x55\xb8\xd5\xe0\xc6\x31\x96\x09\x79\x17\x85\x68\x9d\xc1\x9d\x5b\x15\xa3\x80\x6e\x09\x54\xec\x20\xf6\xde\x0b\xc3\x93\xab\xc1\xde\x40\x4c\x73\x3c\x4c\xd7\x21\x17\x1a\x56\x97\x89\x84\xf3\xbb\xaf\xd2\x77\x8e\xec\x22\x39\xbc\xaa\xc1\x32\x3a\x73\x14\xce\xe7\x48\xc7\x86\xb7\xe6\x97\x7f\xd9\xf3\x4b\xb4\x89\x8c\xa0\x53\xa7\x25\xf3\xb5\x8f\x26\xd9\xa9\x55\xf0\x28\x42\x83\xd3\xff\x3e\x0e\x06\x8e\x3e\x41\xa8\x3d\xfb\x17\xcf\x4f\xff\xe7\xa5\x5f\xf3\xf9\xc3\x61\xcc\xa4\xd6\x7c\x0e\x4c\xd5\xe7\x29\xe9\x3e\xcd\x6d\x5f\xdc\xae\x16\x69\xc1\xd6\x91\xa8\xfb\xf4\xab\x3e\x75\x2d\x40\x4b\x44\x26\xff\x70\x18\x99\xdc\x49\x77\x01\xaa\x0a\xd6\x05\xe0\x64\xc0\xa9\x33\x53\xc6\xa6\xbc\x43\xa0\x82\xe7\x33\xc3\x7b\xc4\x4e\xab\xb9\xb3\xba\x9b\x65\xd8\xaf\xcd\x41\xea\x5d\x08\x95\x62\xa4\x65\xc9\xed\x0d\x43\x8b\xa2\xf3\x0f\x79\x76\xa8\xb4\xca\x6d\x3d\xa7\x74\xd8\x6f\x26\xc0\x13\x20\xd2\x18\x8a\x89\xb8\x72\x75\x7e\x71\x5e\x0b\xf2\x48\xe6\x2e\xd2\x39\x42\xb3\x41\x04\x18\x8d\x59\xf9\xf3\x22\xfd\x22\xbe\xc0\x72\xfc\x95\x93\x5a\xa8\xd5\x2c\xea\x3b\x85\xb6\xd4\x48\xf8\x5b\xc4\xba\x1f\x16\xfe\xbd\x2e\x09\x15\xa0\xe8\x73\x8a\x52\x4c\x1d\xb7\x57\x79\xe4\x90\xce\x51\xa4\xc2\xe1\xc4\xb4\x23\xfd\x7b\x09\x67\x8c\x1d\x8b\x8a\x56\x5e\x39\x9a\x43\x0d\x54\xb1\x99\x18\xd4\x4c\x30\xf7\x0a\x17\xd1\x7c\x69\xc6\xed\xfd\x85\xf8\x28\xf3\xed\xf6\x84\x91\x26\x05\x9a\xb7\x22\x42\x1a\xb2\xf9\xcd\x60\xb2\xee\xe7\x86\xc7\x5c\x29\x93\x82\x5c\x75\xe6\xf7\x8c\xb2\xcd\x20\x6c\xc9\x00\xb7\x24\x89\x6a\x4f\x3d\xfa\x51\x4b\x58\x9d\x89\x47\xc0\x2c\x87\x5d\xf3\x8e\xc6\x67\x7b\x26\x1b\xf8\x61\x3f\x4d\x81\x63\x9b\x57\x49\x53\x39\xba\x80\x8f\x04\xe4\xae\x11\xfa\x99\x1b\x22\x8b\xdc\x75\x8c\xc0\x46\xe1\x22\xfa\xc1\x9b\xac\x20\x59\x47\x2f\xfd\x3a\x4d\x57\x7c\xe1\x4f\xc9\xb4\x67\x36\xe9\xad\xc9\x6e\x2e\xed\x15\x65\x71\xba\x94\x15\x67\xe9\xe7\x5e\xaa\xaf\x89\x1e\x10\x06\x54\x69\x0e\x90\xd3\xa3\x88\x2a\xbd\x25\x26\x2d\xba\x49\x7b\x49\x31\xeb\x25\xb3\x19\x19\x2d\x24\x79\x6f\x91\xe6\x2b\xa8\xd5\x13\x93\xad\x87\xa8\x16\x06\x88\xa7\x51\x02\xd9\x6d\x4c\x00\x69\xed\xd1\xc4\x1a\xe9\x4f\x72\xd1\x7a\xff\x96\x95\x39\xbb\xcf\xf4\x82\x93\x54\x61\xc4\x07\xff\x54\x3f\xb8\x31\xa1\x43\xc0\xff\xf4\x22\x3f\x39\xb9\xdc\x00\x19\xd1\x2c\xaa\xf2\x4b\x6f\x3d\x9c\x57\x18\x6a\xe7\x63\xf9\xae\x5c\xc5\xe3\x70\xed\xb5\x5a\xfa\xf1\x30\x17\x2e\x5e\x71\x43\x89\x79\x7f\x9f\x92\xed\x03\xcc\x9f\x04\x08\x32\x6b\xa5\x79\xbd\xcb\x20\x1b\x22\x97\x49\x11\x07\x80\xe6\x4e\x9a\xb0\x8a\x8b\x9e\x51\x8d\xa2\x84\x54\x32\x71\xfb\x56\x26\x6c\x92\x0c\xe1\x8a\x54\x79\x07\xfa\x05\xa6\x75\xc3\x2e\x26\x18\x4a\xd5\xc7\x06\xa3\x9d\x9c\x10\x0f\x1e\x55\x40\x99\x00\x5e\x23\x43\x5e\x62\x3a\x51\x46\xaf\x3b\xcc\x96\x2b\xee\x8c\x16\x1f\x19\xd7\xd7\x30\x02\xca\xa3\xc2\xb1\x4e\xd8\x04\x18\xf8\x80\x87\xc3\x11\xea\x42\x58\x9a\x91\x85\x5b\x75\xc8\x93\xd2\x22\x86\xb2\xae\xfe\x8e\x8f\x77\x0f\x64\x9f\x3a\xfd\x00\x06\x18\x0c\x8e\xe0\x0a\x18\x79\xcc\x8e\xb7\x91\x42\x3f\xee\xc9\xf9\x1f\xc1\xd9\xbb\xbf\x3f\xf2\xa5\x6e\x41\xe2\xfa\xbc\xe9\x65\x02\x67\x8b\x92\xa8\x7d\xeb\x68\x13\x99\xd8\x67\x22\xd3\xbe\x25\xe8\x25\x1a\x0b\x0c\x5c\xf5\x11\x0d\xfd\x9b\x6c\xad\xc8\xf0\xe7\xa7\x5f\xde\x7d\xfa\xc8\x02\x62\xd9\x05\xc0\xc9\x05\x8b\x8b\x51\x44\xfc\xf1\xd5\xbf\x7f\x7c\xfe\xfe\xd5\x73\xbb\x8e\x24\x4c\xee\x28\xdd\x02\x89\x00\x12\x8a\xeb\x46\x7f\xd1\x4b\x1a\x9f\x03\xf9\xe3\x94\xbc\xd8\x02\x12\x11\x2c\xd1\xc6\x1f\x1e\x96\x40\xe8\x92\x08\x80\x57\x82\x85\x02\x75\xfd\xa5\xac\x66\x2c\x01\xc0\x58\xdb\xc8\xf0\x03\x9b\x37\x5d\x30\xcb\x9f\x1b\x9c\x7f\x28\x7b\x59\x57\x54\xfc\x25\x4d\x29\x6a\xac\xef\xb8\xef\xb0\xfe\xb2\x88\xb0\xe3\xe3\x87\x72\xa6\xb8\x1b\xb6\x15\x56\xb7\x05\x96\x52\xb5\x51\x87\xfb\xa9\x7b\x3c\x26\xec\x2d\xf7\xa9\xb0\x20\xcd\x58\xdf\x02\x2b\xbe\xd0\x00\x05\xb9\x0a\x22\xb6\x10\x91\x1e\xc8\xae\xf8\x89\x02\xae\x17\xe8\x94\x6c\xd8\x4f\xba\xe2\x44\x2f\x6b\xfb\xa3\x87\x4f\x70\x6f\x29\x31\x60\x73\x04\xc4\x9d\xb6\x06\xa1\xad\x3d\x0d\x15\xb0\x77\xdf\xbe\xc1\x2b\x83\xae\x46\x37\xe6\x12\xa9\xdd\x55\x26\x3d\x31\x36\x61\x10\x1c\x96\x03\xd2\x56\x96\x97\xb1\xd6\xa5\x61\x06\xbd\x32\xc4\xf5\xb4\x64\xb7\x99\xf4\xa2\xd6\x34\xaa\x3d\x3b\xdf\x24\x0e\x63\x07\x5c\x65\xa8\xfa\xb4\x30\x8c\x31\x5b\xaa\xd7\xfb\xfb\x3e\x5a\x4b\x4b\xc3\x7a\x16\x72\xa3\xf5\x07\x5e\x00\x3e\x8c\xf1\x2d\x3c\x41\xaf\xec\xa3\xa9\xc8\xbf\x25\x79\x36\x93\x37\x13\x2c\x51\xd8\xb4\x0c\xc8\xb4\xb1\x58\x5b\xec\xd8\x61\x2c\xb6\xdb\x34\xec\xc7\xbd\xc8\xa6\x70\x2b\x93\x3c\xb1\x99\xf3\x4a\x66\x22\x11\xfe\x10\x78\xbc\xa4\xfc\x7b\xb8\xc4\x30\x01\xad\xd2\x2f\xe9\xf5\xaf\x59\x63\xbc\xb1\xae\x99\xfb\xfb\xbb\xcd\xce\xab\xe6\x6c\xe4\x21\x3f\x0c\x8c\x60\x0c\x06\x46\x0c\xf7\x76\x85\x71\x26\x60\x8b\xab\x18\x83\x4e\x28\xab\x35\x2c\x1d\x5e\xc3\xb0\x30\x5f\x41\xeb\x10\x9b\xad\x00\x5e\xfa\x91\x3a\xfe\x16\x0b\x8d\xef\x82\xef\x4e\x10\x31\x9e\xc0\x83\xb9\xd3\x29\x69\xb4\x3e\x6a\x99\x05\xf0\x28\x7f\x04\x1a\xac\x46\x1b\x8a\xf6\x2e\x6f\xab\x1e\x8d\xbf\x1f\xd1\xf8\x0e\x48\xc3\xd5\x21\x05\x01\xe6\xfc\x7f\x5d\xf4\xfe\x5a\xfd\xb5\xf8\x6b\xf3\xd7\xf9\xe5\x03\x64\x95\x9f\xf6\x8f\x4e\x4f\xef\x51\xc2\x7e\x5f\x94\x6c\x6c\x77\x8f\xea\x95\x7b\xf1\x5c\x37\xb7\x79\x3a\xd0\x5f\xfd\xf5\xc1\x33\xf8\x30\x71\xa2\x29\x34\x86\xdc\x3e\xa5\x0c\x37\x3e\x76\xf8\xcd\x87\xe7\xab\xd5\xf1\x31\xfd\xa1\xa8\x73\x9f\x8a\x3a\x99\xa7\x3f\xe3\x05\xf8\x5a\xb4\x07\x90\xe7\x36\xbe\xb5\x7e\xdf\xf4\x5f\xb2\x46\x31\xa0\x80\x10\x0a\xa4\x19\x8c\xea\x1d\x64\x64\x6d\x2a\x20\x7a\x48\x30\xc1\xdd\x6e\x14\x7a\x86\x47\x88\x5c\x4b\x10\x51\x68\xa9\x7f\x49\x22\x9d\xad\x0d\x1b\xce\xea\xd7\xa4\x75\xc3\xe9\x3f\x9e\x92\xdd\xdb\xc5\xe8\xf2\xf8\xb8\x94\xc5\xf6\x3c\x82\xbf\xae\xe7\xe9\x7c\x0e\xf4\xbe\x20\x95\x2d\x11\xe8\x98\xc4\x8f\x33\xed\x6b\x71\xde\xd8\xe6\x8d\x98\xd3\x7b\x46\x7a\x4d\x74\xc8\xe8\x8f\xc2\xf1\x40\xb8\x05\x39\x6b\xa5\x61\x32\xd9\xe3\x90\xee\x92\x41\xee\x03\x8b\xbb\x0f\x8a\xc4\x90\x64\x46\x2d\x06\x4b\xec\xb7\x0b\x7c\x86\x70\x10\xc1\xaf\xb2\x10\xd9\xbe\x32\x46\x54\x3f\x39\x2d\x53\xe0\x0d\xca\x04\x3e\x30\x51\xd9\x8e\x15\x0a\xf7\x38\xd1\xa1\x3b\x2d\x60\x80\xcf\x68\x69\x0f\x73\x2f\x66\xf0\x33\x1c\x4e\x45\x24\x9c\x82\xae\xf4\xa2\x9b\xd4\x28\xf0\x66\x3f\xf2\x5e\x97\x0d\x5c\x8c\x68\x95\x01\x7f\x0c\x46\x4d\xb5\x97\x62\x7b\x9e\x0f\x81\xe4\xf2\xf4\xa2\x1b\x90\xe3\x6b\x5f\xb9\x67\xa3\xc3\xbc\x7e\x95\xa9\xd4\x11\x72\x6a\xd2\x61\x46\x86\x74\x11\x6c\x01\x70\x7d\x52\x29\x4a\xf8\x48\xf1\x0d\x71\x61\xca\x95\x62\x65\x70\xaa\x2b\x54\x56\x85\x8a\x3e\x57\x7c\x4a\x5c\xe1\x09\x6f\x58\x8e\x9e\x0a\x91\x18\x59\x8e\xd0\x6f\x65\xfa\x02\x00\x3e\xbc\x22\x9f\x5f\x2a\xe7\x47\x49\xb9\x64\xd2\xc9\xee\x68\xbc\xb1\xa5\x3c\xed\xcb\xc1\x11\x91\x9c\x8d\xf6\x36\x03\x17\xde\x33\xe4\x56\xd4\x22\x87\x0f\x71\x6d\x80\xe3\xda\x6f\x71\x65\x29\x96\x0a\x53\xdc\xf4\x74\xcc\xa0\x16\xba\x20\x30\x30\x8c\xa8\x78\x08\x9a\x3e\x24\xa7\x04\x41\x95\x49\x23\x31\x98\xcc\x46\x52\xa3\xc2\xb3\x09\xad\xbd\x4b\xca\x35\x5d\x52\x6e\x67\xa2\x47\x91\x0c\x75\x09\xd0\x6f\x70\x54\x3a\x1b\x7d\x93\x44\x7a\xe9\x9a\x97\xda\x4e\x32\x02\x36\x11\x18\xce\x13\x61\x0f\x15\xa1\x9f\x10\x5b\x29\xf5\x1f\x3e\xb1\x93\x7e\x77\x18\xa7\xde\xa0\x71\xaa\xaa\x97\x18\x12\xe8\xff\x1e\x9c\xe0\x67\x56\x42\x6f\x21\x09\x2b\x85\xf0\x4b\xed\x1e\xc9\x80\x8d\xeb\x18\x76\x6c\x6d\x99\x61\xc7\x6b\x96\x08\xb3\x4d\xb0\x96\x16\x1b\x27\x62\x6d\x9d\x08\xf8\x35\xf5\x10\xbb\xca\x05\x05\xb8\x03\xbe\x38\xd3\xf3\x19\x92\x47\xe1\x08\x66\x0f\x0b\x1b\xb2\xb8\x67\x15\x2e\xc3\x9b\xf0\x16\x76\x14\x46\xd6\xe2\xd2\xe4\xe6\x5f\xc1\xfb\x2b\xed\x02\x76\x05\x1b\xbf\x82\x5d\xbf\xba\x0c\x97\x31\xac\xd3\x11\x59\xac\x9d\x7c\x8e\x66\x03\xe8\x62\x15\x5e\x61\x4a\x9d\xe2\xe4\x36\xbc\x3d\x89\xeb\x3e\x77\x81\x8b\xa1\x05\x6d\xd7\xf1\x5c\x38\xec\x5f\xf3\x12\xbd\x0a\xbf\xc6\xd7\x12\xfc\xa8\xfc\x08\xb9\x5b\x98\x4d\x95\xa5\xb5\x1a\xc8\x17\x18\xc8\x51\xff\x55\xfc\x95\xd4\x86\xfd\xc1\x00\x2e\x8e\x22\x9d\xc0\x68\x5e\x0d\x3f\xa3\xe3\xa0\x7f\x40\x5f\x60\xc0\x5b\x86\xd4\x23\x35\xa5\xaf\x5d\x1a\xdb\x0b\xd9\xf8\xe4\x05\xec\xcd\x2a\x7e\x71\x31\xf6\x4c\x3c\xe9\xbf\x00\xda\x61\x70\xf2\x99\x7a\x1c\x75\xf4\x87\x6a\x44\xec\xd1\x46\x63\xeb\xc1\xdd\xa2\x3f\x3e\x32\xf9\x79\x99\xef\x37\x1f\x8a\x48\xbe\xb8\x2e\x72\x19\x3e\xe0\x01\x7f\x3f\x78\xef\xa2\xf8\x0f\x03\x1a\xe0\xfb\x8b\x0f\xde\x01\x7e\xd8\x63\x74\x32\xc1\x98\x95\x80\xdd\x4a\xea\x2c\x0d\xa1\x47\x68\x05\x0d\xb0\x15\x8e\x74\x54\x81\xa9\x97\xb9\xca\x8d\xd2\xd7\x55\x72\x63\xa7\xba\xb3\x8c\x87\xff\x94\x14\xb3\x3c\xad\x75\x56\xa8\x1b\xb8\x98\x85\x1d\xcc\xeb\x42\xe7\x83\x32\xa5\x11\xb3\x96\x74\x7e\x35\xfc\xf0\xea\xdd\xf3\xf7\xcf\x3f\xbe\x7d\x8f\xa9\xa0\x82\x28\x80\xe5\xb8\x0b\xf0\x21\x1e\x01\x21\x39\xc4\x87\x31\x3c\x44\xf8\x70\x16\x6c\x60\x39\x1e\x5c\xc4\xc3\xc8\x36\x18\x5f\x6f\xe1\xfb\xec\xc9\x40\xe9\xf7\x2d\x43\x68\x39\x97\x68\x7c\x36\x0a\x5b\x53\x01\xa4\x37\xda\x4b\x0e\x0f\xff\xee\x4f\xe1\xb9\x21\x0a\x81\xfd\x6a\xb3\x5c\xed\x30\x62\xd4\x8d\x87\x6f\xd5\x9f\x52\xeb\x79\x76\xcd\x53\x0c\x06\xdc\x92\x2e\x88\x7e\x20\x92\x69\xec\x61\x19\x9d\x46\xea\x6a\x2a\x3f\xc7\xc7\xe8\xec\x8c\xe8\xd8\xf1\xe1\x51\xbf\xc8\x4f\x6c\x5e\xc8\x88\x98\x22\x8a\xbc\x0c\x85\x59\xc2\x16\x20\x7d\x61\x9b\xb9\x91\x13\x87\xbe\xf6\xae\x28\x9c\x60\x1d\xb3\x6a\x22\x34\x5f\xe5\x42\x58\x5e\x5b\xb2\x23\x12\xdc\x90\xb7\x3e\x7f\x09\xed\x9b\x3f\xe1\x2e\x12\xb8\xf7\x82\x02\x6b\x3b\xef\x60\xb4\xf2\x75\xfb\xcd\xa5\xe1\x88\x3e\x0a\x39\x20\x9e\x59\x43\x98\x2e\x54\xa4\x90\x60\x1c\x5d\x0c\x26\xc5\xb3\x74\x92\xd2\x4d\x9c\x5e\xba\x9f\x40\x11\xb4\xab\xaf\x66\x6b\x7e\xe9\x32\x6b\xbc\xca\x9b\x03\x26\x29\x94\x06\x14\x18\xc1\xed\x3c\x9c\xc6\x89\x70\x4e\xa9\x0d\xf2\xc7\x43\xd4\xac\x71\x59\x64\x82\xc6\x35\x6d\x1c\x90\x71\x9c\xff\x1d\xf9\x27\xa9\xb6\x80\x41\x62\xd5\x10\x65\xe6\x53\x11\x95\x7c\x2c\xb3\x18\xe2\x1b\xbe\x40\xd6\x12\x12\x06\x50\x93\x23\x3e\x9f\x6d\xa9\x85\x16\xfc\xb2\xde\xc3\xad\xf5\xf0\xda\x94\x35\x1f\xed\xa8\x09\xe4\x82\xaa\xfb\x78\x67\xdd\x30\xd3\xb5\x9f\xec\x51\x1b\x83\x95\x00\xf5\x8e\xf0\x52\xc7\x63\xe0\xc2\x34\x48\x4c\x4f\xc7\x83\xc9\xf4\x59\x3d\xa9\x01\x28\x92\x8b\xfa\x74\x7c\xa9\xf7\xe1\xa2\xbe\x9c\x50\xb3\xec\x81\xae\xdb\x4d\x98\x15\xa5\xfb\x2e\x07\xcc\xbc\x96\x3b\xc6\x5d\x8c\x26\x2b\xd1\xa2\xdc\x25\x68\x69\xfb\x46\x61\x85\xd6\x5e\x89\x52\x31\x2b\xfc\x21\xb7\xca\x8c\xcf\x7d\xd6\x5d\x0f\x36\xcb\xac\xf9\x70\x5b\x4d\x0c\x9c\xcf\x75\x45\x54\x1f\x8c\xee\x7e\x94\x10\x31\x91\xfb\x57\x2d\x9f\xe4\xb4\x6a\xb9\xbd\x6a\x39\xac\x9a\xe8\x47\x2c\x9c\xd9\x51\x32\x98\xfc\xc3\x3f\x28\x26\x62\x64\x9f\xb2\xb2\x68\x79\x4b\x30\x81\x8c\x7d\x57\xe8\x1e\x01\x4c\x1e\x46\xc6\x50\x26\x54\xd6\xb9\xb3\x10\x48\x7c\xb7\x11\x11\x5e\xf4\x29\x3b\x6f\xe3\x11\xb7\x28\x76\x71\x4d\x98\x5d\x46\xee\x67\x14\x7f\x20\x1b\xb8\xe5\x71\x16\x4a\xa7\x33\x73\x4e\x80\x59\xf7\x9a\x15\x6e\xff\xff\x87\x26\x66\x43\x71\x6b\x8a\x7b\xa3\x45\x9a\xab\x19\x7d\xd9\x1c\x62\xcc\x37\x03\xf9\x1e\xc1\xa4\xc4\x9f\x23\xe2\xdd\xe0\xd7\x51\x45\xeb\x3b\x40\x03\x2d\x1a\x3b\x22\x12\xac\xa1\xc9\x71\xb6\x7b\xab\xe4\x11\x4d\x04\x2f\x46\xca\x01\xbb\x29\x2c\x70\x5a\x33\x8c\x96\x7b\x99\x92\x54\x39\x8b\x33\x26\x13\x13\xf1\x32\x03\xba\x36\xca\x22\x16\x5d\xf5\xdc\xf9\x74\xad\xe2\xf3\x3c\xff\xd9\x7b\x83\x7a\xc0\xe1\xbc\xdf\x9c\xfb\x9b\x8f\x1c\x30\x09\x39\x8a\x8c\x07\x26\xe7\xf3\xb8\x7b\x2b\xad\xaa\xc9\x6c\xa6\xb6\xd8\x06\x6b\xab\x5a\x8d\x4e\xb8\x5f\x3d\x73\x68\xb9\x63\x92\xe2\xf9\x15\x5c\xa7\x0d\xb6\xe8\x14\x9c\xb5\x4a\x1e\x42\x49\xcb\x34\xfe\x6c\xec\x91\x29\xf7\xcd\x75\x3b\x32\xde\x52\x0a\x8f\x02\x77\x0a\xff\xb9\xbf\xaf\xfa\x83\xd0\x27\xe5\xa5\x40\x68\xa2\xa7\x73\xdd\x27\x7e\x14\x79\x2e\x62\xfe\xfe\xf8\x98\xff\x0e\x93\xe5\x4c\x3e\xf7\xdb\xb3\xc7\x46\x36\x83\x4d\x3f\x00\xf6\x63\x99\xa1\x37\x89\xd7\xec\xea\xbc\xa1\xdd\x32\x6d\x22\xfc\x64\x5d\x23\x6c\x3c\x71\x7f\x38\x36\xca\x0a\xd0\xc4\x2a\x9e\xf5\xe7\x98\x48\x27\x43\x1b\x4c\x55\x39\xb5\x5c\xb0\x24\x77\x6d\x73\x28\xc0\x27\x0b\x16\xeb\x08\x9d\xad\x4c\xbf\xcb\x02\x15\x51\xe8\x58\xb0\x48\xe1\x4e\xef\x30\xde\x37\x09\x47\x1c\xb6\x3c\x7e\x0d\x5c\x87\xcd\x53\x26\x39\x17\x30\x2e\x79\x0e\x1b\xa4\xc2\x58\xa7\x85\xe7\x87\x2a\xd4\xe8\x87\x71\xae\xeb\x22\x46\xaa\xd7\xd3\x29\x26\x3a\xb1\x4b\xe7\x49\x96\xaf\x2b\x41\xbb\xca\xd2\xc1\xa4\xd5\x4d\x3c\xda\x58\x94\xb0\xce\xe6\x12\x96\x14\x6b\xa8\x20\xc3\xb2\xf3\x0a\x8e\x00\x4e\xbe\xdf\x0c\x97\xf5\xcd\x20\xea\x03\x72\xc6\x37\xa3\x73\x2a\x88\xc4\x95\x29\x08\x5f\xae\x04\xc8\x09\x73\x9f\xac\x78\x43\x75\x13\xc8\x90\x0a\x0b\x18\xb1\xd9\xa7\x34\xa4\xde\xf4\x76\x9a\xa7\xc1\x00\x5a\x2f\x63\x34\x21\x43\x4f\x58\x6a\x36\x0b\xf1\xe3\xba\xcc\x3f\xa7\xa1\x6c\x66\x10\xa9\x32\xac\x2a\x84\x4c\x09\xc6\xf7\x11\xfd\x00\x15\x62\xd2\xea\xd2\xdc\x24\x5c\xa3\x51\x16\xa2\x54\xc4\xc0\x53\xf4\x19\xbf\xb9\x49\xab\x74\x06\x74\x85\xfe\x41\xd1\xbc\x30\x80\x1f\x60\xd4\x69\x4c\x4f\x03\x5a\x90\x7e\x02\x63\xab\x60\x6c\x7d\xb6\xe5\xa9\xfb\xd3\x41\x98\xf0\x38\x2b\x13\x2e\x33\x79\xbb\x87\xea\xea\x07\x46\xc5\xa8\x50\xfa\x2a\xe0\xec\xa7\xb8\x7c\x71\x05\xfd\xd3\x86\x03\x71\x31\xb5\x36\xed\xd9\x08\xe8\xa4\x7e\x01\x94\x90\x9c\x76\x8e\xad\x31\xd1\x02\xb8\x5a\x8e\x2a\xc7\x14\x5a\x86\x34\x2a\x55\x0a\x37\x9c\x7d\xa5\x27\x8b\x5a\x36\x7b\xea\x95\x98\x7a\x15\xd3\x13\xea\x5b\x70\x4c\xb8\xfc\x3c\xa6\x33\xd4\xc0\x78\xc6\x54\x0d\x6c\xc1\x96\xcc\x10\xa4\x72\x03\xa0\x70\x48\x87\xbe\xca\x00\xca\x35\x2a\xca\x50\xe4\x2f\x37\x35\xbd\xc8\x2e\x07\x74\xa6\x2c\xc4\x05\xb5\xd0\xeb\x13\x05\x68\x50\xdf\x92\x93\xe9\x18\xf2\x92\x89\x33\xe6\x34\xb6\x64\x10\xa2\xaa\x80\x4d\x59\x9d\xa7\x36\x6a\x7f\x6b\x9c\x23\x15\xcc\x0e\xd7\x43\x78\xe4\xa8\x96\xa7\x7d\x16\x61\x7b\xbc\xb2\xd3\x01\xdb\x6a\x19\xd0\xff\x4b\xd9\xf4\x12\xa5\xeb\x0e\x48\x52\x35\x3a\x12\x67\xfd\xea\xea\x97\x77\x6f\xaf\xae\xba\xbe\x12\x23\x0f\xc4\x99\x16\xb5\xe3\xb1\xa0\x13\x10\x06\xd6\x1c\x24\x8d\x2b\xe0\x3a\xea\x4b\x27\x05\x16\x41\x78\x19\xdf\x49\x04\xd2\x85\xb7\x46\xa1\x40\x26\xbe\x1a\xd9\x79\x86\x98\x4d\xa7\xae\x91\x2b\x8a\x03\x70\xc3\xc6\xf7\xcd\x1b\xa9\x6b\x9d\x1a\xaf\x4f\xfb\x3e\xab\x57\x4a\xd0\x81\xed\x2c\x05\x12\x40\x0d\x98\x82\x54\x22\x59\x80\xd7\xc1\x35\x16\x70\x2c\x81\x36\x54\x23\x67\xa2\xe0\x22\xa0\x83\x15\x5c\x76\x12\x1b\x04\x98\x12\xdf\x0d\x36\x84\x1b\x52\x0b\x0b\x5a\x8c\xbe\x44\x10\x8d\x89\x03\x1a\x75\x6c\xe9\x85\x81\xc4\x54\x31\x22\x31\xc1\x46\x85\xf3\x70\xd1\x36\xc5\x90\xa2\xe7\x70\x16\xfb\x6e\x4c\x54\x45\x2d\x97\xe9\x0c\xad\x46\xcf\x3d\x73\x31\xdf\xa3\xdc\x39\x82\x82\x8f\xd9\x32\x2d\xd7\x0d\x4d\x49\xf4\xc7\xed\x2a\xd1\x20\x90\x4e\xc1\xd7\x20\x44\x42\x3b\x6f\x71\xfd\xaa\x6d\xff\xb7\x58\xeb\x8e\x24\xa0\x51\x11\x7e\xa9\x32\xf2\xab\x21\xdf\x2a\xca\x10\xb0\xae\xe8\x77\x85\xd6\x6c\x63\x4c\x02\xc8\x6b\xf2\x79\x70\xe7\xf6\xa4\xf7\x83\x32\x0e\x84\x18\x5f\xc3\xa4\xab\x5c\x5a\xc0\x11\xf0\xd4\x69\x3e\x57\x89\x4e\x50\xd2\x63\xb8\xd7\xd1\x3c\x04\x50\xdf\x01\x05\xa1\x03\x0b\x91\x44\x83\xcf\x57\x43\x3f\x42\x0c\xf4\x4a\xdf\x57\x11\xe6\x0d\x28\xe0\xbf\x4a\xb6\x15\x12\xa9\xd1\x4e\xa8\x20\xec\x85\xe0\x0e\x5d\x89\xaa\xe8\xd7\xd2\x28\xd6\xb3\xa1\xd1\x01\x17\x13\xb3\x4b\x0b\xe0\xf1\x3e\xcb\x70\x97\x71\x4e\xab\x6f\x1c\xab\x20\x9c\x86\x86\x71\xf4\xd4\x48\x63\xb0\x0c\xf3\xfe\x32\x0c\x04\x76\x40\xe1\x2a\x86\x13\xc9\xfb\x53\x34\xa2\xa4\xb3\x12\x58\xd0\xa8\xbd\x45\x27\x5a\xe7\xe1\xb3\xe4\x23\x92\x44\x62\x1d\x20\xca\x70\x3d\x0c\xb2\x4e\x32\x38\xbe\x93\xec\x3d\xdf\xc5\x1e\xe7\x9b\xe0\x13\x75\xff\x62\xfc\x34\xa8\xd0\x03\xd3\x12\xf7\xfc\x9d\xc7\x53\x58\xe3\x81\x6d\xdb\xb1\x96\xc1\x05\x2f\x24\x0b\x09\x2e\xa1\xb3\x85\xd4\x51\x9c\xa7\x1e\xe2\x88\x3a\x84\x4b\x94\x43\x78\x0d\xa2\x11\xad\xb9\x60\xa3\x52\x75\x4f\x5e\x5c\x0e\xdc\xe5\xa7\x43\xe8\x9f\x6e\xe1\x9d\x6e\xb5\xc7\x74\xa5\xea\x53\x08\x0e\x4b\xa1\xc2\xcb\xd0\x30\x7e\x34\x49\x60\x8d\x1b\x27\x8c\x1e\xfa\x09\xc3\x09\x3b\x39\xa9\x91\x01\x3c\x3e\x2e\x00\xf9\xd2\xc5\xad\x37\x91\x3c\xd0\xff\xae\xab\xf6\x7f\x62\x69\x7c\x93\xc7\x98\x76\x6a\xb2\x53\xfc\xd7\xb0\x52\xf3\x61\xea\x9b\xbc\xbc\x4e\xf2\x73\xfe\x13\xf9\x71\x79\x3e\x3f\xc7\x7f\xbc\x6f\x85\x6f\x12\xff\x89\x00\x35\x4b\x56\xd0\x63\xd2\xa1\x99\x37\xb2\xdc\xa2\x6a\x1e\xf3\x84\x42\x98\xd2\xcc\x3e\x00\x9a\xc1\x7c\x94\x97\xa1\x2a\x7a\x4e\x35\x45\x19\xe5\xdb\xb4\x70\x2f\xea\xc0\x9c\xcf\x25\xcd\x37\x70\xcb\x57\xe5\xaa\xcf\xea\xa8\x89\xdb\x7c\xfb\x1b\xf9\x82\x3e\x52\x83\xef\xb4\xd4\x24\x25\xc1\x9a\x32\xdf\x29\xd3\x94\xff\x2c\xb3\x02\x7e\x0e\xa5\x6d\xe9\xbf\xc0\xef\x17\xd8\x3a\xf9\x4a\x9b\xd0\xa8\x44\xe8\x22\x76\xe5\xdd\x66\x52\x3c\xed\x37\x1c\x83\xac\x4a\x01\x62\xe0\xf4\xc9\x31\x9e\x9c\x14\x03\x8e\xcf\xc1\x2f\x31\x90\x2b\x5e\x4d\x64\x68\x89\xe2\x74\xf8\xc7\x30\xad\xb4\xac\x5d\x0c\x13\x48\xe5\x96\xc8\x7a\x77\x69\x72\xc0\x61\x61\x4b\x3c\x6f\xeb\x38\xe9\x03\x5d\x47\xb6\x8f\x99\xaa\x3f\xc5\xfa\x6b\xae\x9f\xc7\xeb\x8b\xe9\x25\xd6\x38\x41\x93\x99\x15\x5c\xb2\x18\x19\x12\x98\x82\xcb\x38\x57\x6a\xb9\xd4\x34\x3f\xbd\x5b\x24\xb5\x14\x4f\xf8\xe3\x01\xb3\xb0\x98\xe8\x77\x96\xb7\xd5\xeb\x6b\xb6\x25\xc3\x0d\x71\x96\x22\x23\xf9\x52\x05\xe0\x21\x63\x8f\xb6\x3f\x01\x02\x5f\xe8\x45\xf0\xca\x1f\x84\x29\x9a\x02\x3c\x55\x92\x28\xd4\x43\xa0\x39\x48\x8c\xab\x17\x16\xac\xba\x26\xbb\x77\x39\x4e\x40\x29\xe6\x4f\xad\xaa\x3e\x1a\x49\xa3\x94\xf1\x26\xe4\x2e\x3e\x96\x6f\x92\xe2\xd6\x93\xa9\x21\x31\x75\xa1\xc2\x0e\xe6\x4e\x1a\x1b\xe2\x91\xbd\x4e\xa6\xbf\x52\xc8\xba\x82\xec\x96\x16\x94\xb2\x0c\xe8\x5e\x7a\x2a\x2e\xcf\x0b\xe1\x98\x3f\x29\x85\xf8\x5a\x76\x48\xd6\xa9\x68\x51\x4b\x9f\x9c\x04\x22\xeb\x54\x70\xc9\xe2\xcc\x8b\xd2\x2a\x2a\x11\x9a\x3f\xa3\xe6\x1d\xc0\x9c\xa7\x04\x64\x9d\x37\x30\xbc\x90\x07\x9c\x07\x72\xe6\xbd\xac\xee\x15\x88\x95\x60\x1d\x7b\x4d\xd9\xe3\x11\xe0\x53\xd6\x20\xc2\x08\x80\x59\xce\x6a\x65\x59\xd7\x88\x21\x62\x68\x1d\x6b\x39\x1b\x7b\x39\x91\x7d\x30\x3a\x99\x26\x05\x76\xa2\x1b\xc7\x0a\x3d\xbd\x83\xbd\xeb\x74\x8a\x91\x40\x7a\x80\x8d\xd0\xb3\x79\x9d\x23\x28\x96\xe5\x2a\x10\x2b\x14\x35\x27\x01\x0e\x15\xe8\xec\x1a\xe6\x06\x48\x54\xb4\xb5\x4c\x9b\x45\x89\xd1\x49\xe4\xd2\x79\x53\xda\x0a\x4f\x9a\xb8\x0d\x49\x9e\x22\x84\x47\x75\xd8\x86\x84\xc3\x7f\x12\x1a\xb4\xd6\x22\xb3\x41\x2f\x91\x87\x29\x10\x9b\x3f\x71\x44\x68\x11\xf5\x02\xf5\x34\x74\xef\x51\x6d\x6a\xe1\x02\x9d\x04\x98\x74\x1c\x98\x18\x43\x92\x77\x68\x56\x38\x4b\xbf\xbe\x9d\x03\x29\x3f\xd1\x9d\x9f\x12\xd5\x14\x06\x1f\x2b\xf4\x3a\x82\xf5\x63\xb1\xa2\x5c\x84\x24\x07\x1c\x34\xbb\xed\xdd\x94\x45\xda\xc3\x70\x37\x3d\x6b\x42\x54\xed\x88\x02\x2c\xd4\x2b\x0a\xfa\xd9\x84\x18\x1b\x0e\x53\xb1\x25\xc0\xc6\xa1\x57\x77\x19\xea\xdd\x88\x9a\x0d\x54\x25\x9e\x27\x19\x84\x09\x27\x34\x53\x53\xb6\x96\xd8\x45\x74\x59\xd7\x7a\x16\x4f\x33\x33\x68\x35\x0a\x9e\xe3\x0c\x81\x3c\x35\x0e\x72\x6c\xc6\x36\xa6\x04\x68\x7d\xe4\xc1\xf4\x2a\x1c\xa1\x38\x58\xae\x10\x9c\xfb\xe0\x35\x30\x98\xbe\x15\xd9\xb2\x08\xd6\x09\x77\x66\x66\xc5\xea\x36\x24\x6d\x61\xda\x35\x2f\xa0\xc8\xd5\x4d\x83\x46\x9b\xed\x51\xcb\xf7\xc8\x9e\x9f\x8e\xbf\x65\xc8\xc0\xf7\xb9\xc0\x15\xd9\x24\x43\x1a\x0b\x05\x18\xc3\x97\x34\x0b\x15\xa2\x2a\xeb\x04\xa3\x0c\xde\x39\xd2\x68\x10\x60\xb4\x3d\xd0\xc6\x6a\xce\x9b\x3e\xc5\x2c\xb3\xbe\xce\x58\x76\x79\x9e\x39\xf2\x16\xa4\x14\x58\x48\x55\x58\x42\xaa\xc8\x0c\x2c\x9e\x21\xe2\xc2\x3b\xf5\x23\x30\x3b\xe8\x79\x1f\x65\xfd\x00\x83\x6f\xc2\x36\x61\xf1\xcf\x00\xd5\xa2\x94\x0c\x5c\x45\xf1\x0b\xba\x16\xb0\x14\x49\x67\x2e\xfb\x40\x62\x5c\x2c\x13\x02\xdd\x81\x30\x2c\xe7\x2b\x3b\x3a\x3b\xa3\x4c\x23\x7c\x9f\xc3\x2f\x32\xf4\x1a\x7b\xcc\xe6\xba\x2f\x7f\x89\xcd\xde\x10\xca\xa9\x6d\x5b\x32\x34\x8f\x49\x8b\x59\xff\xce\x1b\x76\x36\x1b\xb6\x01\x6d\x83\xd3\xa7\x21\xba\x0d\x47\x40\x95\x78\x06\xeb\xb1\x4a\x6b\x0f\xd6\xbc\x97\x57\x55\x8a\xa2\x7e\x13\xa2\x01\xe2\x17\xe5\x3a\x9f\xb9\xe5\x5a\x69\xc8\xd0\xd8\x86\x2f\xbe\x79\x04\x64\x69\xa2\x18\x48\x62\x8c\x87\xc3\x5b\x4d\xf6\x37\x21\x4b\x09\x29\x64\xbc\xa5\x73\x4b\x59\xed\x60\xea\x3d\x18\xab\x92\x56\xe5\xe7\xe4\x3a\xcd\x11\x63\x9a\x82\x50\x16\x28\xca\x0f\x1d\xe5\x6e\x65\x7f\x08\xfb\x2d\x04\x31\xbe\xa4\x4a\x1c\xc6\x48\x08\xe3\x98\xca\x52\x88\x24\xc0\x3d\x43\xad\xcf\x2c\x18\x3c\x8b\x47\xe2\x2e\x6e\x57\x9b\xd3\xc9\xa5\x3a\x24\x01\x96\xac\x9e\x76\xcc\xfc\xee\xdd\xfa\x1a\x16\x70\x01\x57\xde\x72\x5d\x37\xbd\x45\x02\xe7\xdb\x68\x9e\xbc\x40\x65\x3b\x3d\xea\xa1\xb7\x92\x9f\xd4\xdf\x0d\x26\x4d\x5b\x6c\xa9\xf0\xa1\x6a\xa6\xef\x8a\x82\x54\x15\x6e\x99\xb9\x4b\xb1\x93\xcf\x8b\xd9\xbb\xd6\xb2\xd8\xd9\x0e\x27\x6a\x7b\x45\x4e\x05\x80\xdc\x17\x70\xb4\xc4\x77\x71\xdf\x57\x7a\x7f\x3f\x1a\x9c\x8c\x4d\xe5\xa2\xb8\xe6\xcc\xfd\x23\xef\x22\x77\x91\x82\x57\x5f\x57\xc0\x7a\x01\x0e\xd4\xac\x50\x8f\xa7\xc0\x57\xbb\xd8\xc6\xde\xf5\xba\x81\x2b\xad\xe9\xa1\x01\xa4\xe8\x48\xa1\x12\xba\x58\x25\xd4\x55\x86\x7f\xb7\xf8\x58\xba\x26\xe1\x19\xd3\xde\x5b\xc6\xd8\x0a\x77\x42\xa7\xa7\x61\x25\xbe\x42\x58\x12\x42\xdc\xb6\x04\x46\x0f\x41\x5c\x0a\xe2\x98\xc9\x68\xfa\xb4\x8c\xb0\x93\xb1\x76\x33\x3e\x6f\x88\x8a\x92\x31\x52\x31\xe2\xf9\x79\x1a\x5d\x18\xc1\xf5\x85\x60\x49\x9d\x4d\xbb\x31\x01\x91\xf2\x1c\xe0\xdf\xd6\xc9\x41\x98\x10\x63\x7e\x5e\xdf\x16\xd3\xdd\x03\x07\xfa\x02\x25\x44\x1f\xb3\xe9\xaf\x36\xde\x16\xcd\xa8\xe5\x65\x70\x12\xa5\x2d\x60\x32\x53\x7d\x42\xcb\xba\x97\xdf\xf1\xb8\x85\x44\x51\x13\x1b\x27\xfa\xd7\x23\x96\x96\x42\x8d\xbb\xa1\x92\x92\xa0\x7d\xf0\xcf\x55\xba\x4f\x08\xa0\x99\xa8\x27\x43\xe0\x6d\x06\xf5\xc7\xb3\x49\xa2\x3b\x5d\xb1\xd0\xcf\x2a\x9f\x82\xa9\xb6\x69\x9c\xe5\xc4\xb3\xb7\xe1\x1c\x51\x03\x76\x62\x6e\xf4\xc9\x6e\x9d\xa1\x06\xe3\x94\x03\xe1\xd6\x47\x72\x0d\xf7\x01\x89\x58\x71\xcc\xb7\x55\x26\x4b\x60\x42\x27\x06\x48\x98\xf9\x1e\x80\x01\x45\xfa\x4f\xab\xe0\x37\xe2\xbe\x74\x2e\x1d\x8f\xcd\x9f\x4f\x04\xb0\xd5\x66\xcf\xc6\x3b\x0e\xc3\x04\x0b\x21\xa4\xbd\x40\x6c\x18\x46\xa4\x2f\x53\x26\x84\x4a\x60\x2e\xbc\xe2\x60\x79\xfb\xed\xf8\x9a\x2e\x25\xf6\x1a\x67\xeb\x59\xbf\xac\x46\xbe\xf3\xb9\x3f\x0c\xd0\xc2\x26\x2b\xd6\x00\x1f\x14\xa4\x15\xfe\x61\x3f\xb2\xc6\xb0\x56\xca\x38\x83\x8d\x5f\x40\x94\xed\xd5\x70\xa6\x5a\xd5\x71\x9f\x79\x7d\xcf\xb6\x7b\xc0\xd1\x91\xd1\x84\x4a\x9b\x14\xb0\x77\x40\x48\xa7\x1d\xe2\xce\x13\x02\x3f\xdb\x4e\x27\x9e\x9b\x18\xae\x4d\x2b\x02\xd5\xc3\x02\xb8\x3e\x72\xe1\x17\x9e\x1a\x97\x03\xcc\xf4\xa2\x23\xf5\xbf\xcc\x66\x6f\xdc\x30\xfd\x99\xa4\xac\x08\xbf\x54\x43\x87\x58\x1a\x18\xb4\x2e\x30\x54\xe6\x88\x58\x54\xdf\xb8\xf4\x32\xa2\x7e\x59\xdc\x77\x86\x78\x39\x40\x7d\x8c\xc5\x89\xa3\xc3\xeb\xc6\x9f\x4c\xc0\x18\x0c\x06\xda\x18\xfa\x2a\xc9\x63\xc5\x5b\x84\x46\xa6\x6d\xca\xee\xcc\x63\x72\xfa\xad\xbb\x6b\x1a\x48\xc7\x99\x4d\xf8\x9f\xa3\xde\x64\xdb\xb6\xa3\x57\xc8\x2e\xd6\xc0\xad\xa3\xfd\x93\x0b\x83\xb2\xf7\x6c\xb6\xbc\xc2\x77\x56\x53\xf1\x21\xed\xcd\xa9\x18\x5a\x04\xf0\xfe\x2e\x60\xc3\x32\x19\x47\x9c\xe6\x99\x60\xa9\x01\x46\x8c\x9e\x9d\x9d\xd5\xe1\x57\xb3\xc2\xf2\x49\xd9\x05\x5f\x15\xc2\x57\x1b\xc0\x92\xbf\x3b\x80\x79\x6c\x7a\xba\xf9\x1c\x09\x6f\xc2\xd3\xee\x5f\xd3\x74\xc5\xb9\x10\x25\x3f\x31\x36\x99\x08\x64\xa2\xad\xf5\x6b\x50\xd8\x06\x8c\x06\x52\x3c\x8c\x9b\x65\x90\xc7\x3b\x4e\x66\xc5\x49\x3d\x36\x03\x3b\x03\x78\x36\x64\xf9\xac\xdc\x20\xb2\x91\x24\x19\x68\x36\x54\x54\xb5\x78\x89\xe2\xd0\x16\x55\xf9\x82\x65\x4c\xc0\x21\x54\x55\x36\x4b\x7b\xcf\xdf\xfd\x24\xa4\x43\x18\x19\x05\xc5\x47\x45\xef\x7d\x3a\xcf\xd7\x5f\xed\x9e\x86\xbd\x4f\x35\x86\x67\x29\x1b\x22\xdb\xf9\x8b\x02\xc6\xd8\x2b\x2b\xdd\x5a\x06\x2d\xab\xef\xdd\xf1\x50\xac\x01\xe0\x55\x31\x88\x8b\x23\x84\xe5\x69\x14\xfe\x69\x14\x87\x4e\xa3\xe0\x69\x24\xc2\x66\x00\x09\x22\x78\xf8\x9d\x67\xa0\xe5\xd0\xb1\x2d\xaf\xc6\xfc\xe4\x48\x47\xbc\x4f\xeb\x75\x8e\xe1\x30\xbc\x35\x25\x51\x7b\x61\xd0\x79\xa1\x24\xe6\x2e\x8d\xa4\x1c\xeb\x18\xd3\xde\xdd\x6d\x26\xeb\xa7\xc6\xd7\x42\x98\xb2\x96\x99\xcd\x72\x53\x2e\xbe\xbe\x9c\x4c\x2f\xf2\xcb\xb8\xee\xe7\xec\xe8\xb1\x32\x38\x6f\x4d\x0c\x47\x01\xaf\x50\x10\x0a\x92\x99\x74\x39\x95\x65\xfd\x86\xd9\x03\x19\x0e\x22\xb6\x95\x75\x97\x24\x74\x20\x12\xfd\x74\xe7\x1e\xeb\xbb\xf9\xc5\x7c\x88\xab\x72\x1e\x08\x5a\x2b\x88\x02\x9b\x56\x0e\x2e\x05\xe5\x35\x37\x29\x43\x2d\x62\x14\x13\x98\x87\xd3\x70\x85\xf6\x04\xae\xbe\x02\x05\x71\x73\xe8\xdc\x14\xba\xd7\x7c\xea\xe9\x70\x46\x67\x63\x11\x62\x71\x0b\x0a\xf0\xe8\x72\x0e\x47\x01\xf4\x6b\x99\x7d\x25\x4f\xdc\xba\x1b\x23\x88\x90\x56\x48\xce\xf8\xa4\x25\x96\xfc\x50\x9b\xd2\x69\x4b\xba\x91\xf2\x59\xb0\x85\xb5\xd2\x82\x46\x6c\x6b\xec\xd9\x56\x87\x2f\x8a\x03\x4e\x7b\x1b\x84\x6b\xc9\x4d\xe9\x34\x8b\xae\x24\x4c\x96\x4b\x86\x0b\x9f\x65\x32\x4b\x2d\xa5\x64\x37\xb0\xd4\x55\x50\x98\x15\xdc\x1c\x7d\x16\xc6\x47\x6d\x02\x09\xf8\x07\x1b\x81\x2b\x6d\xa4\x91\x0d\x49\xbb\x65\x22\xc2\x9a\x30\x48\xdf\x8b\x42\x80\x90\x77\x6f\x37\xf2\xd2\xfd\x26\xcc\x22\xd0\x83\x39\x80\xdf\x03\xbb\x3c\x90\x6f\x9c\x81\xfa\x10\xe7\x54\x23\xce\xfa\x62\xda\x31\xed\xa9\x77\xda\xd3\x83\xa7\x3d\xe5\x69\xd7\x38\xdf\xdf\x15\x9f\xee\x33\xe3\x86\x34\x48\xa1\x42\x00\xa9\x11\xbc\xad\x35\x39\x3f\x86\x32\x37\x2a\x14\x52\x92\x9c\x8e\x45\xaa\x2d\xab\x1c\x9d\x29\xa2\x93\x7c\x10\xe6\x1b\x0f\x0a\x31\x4f\x2c\x94\xfd\xd8\x46\x2b\x7c\xfa\xe1\xd7\x0f\x1e\x24\xe3\xd5\x04\x5b\x58\x94\x11\x83\x55\x14\x60\x1c\x3e\x67\xb6\x1d\x12\x57\xa8\xe8\x2e\x02\xd7\x74\x4b\xa9\xaa\xb9\x38\x22\xcd\xb0\x51\x42\x55\x44\xfa\x23\x1a\x8e\x95\xbe\x49\x28\xe8\x55\x15\xfa\xd2\xac\x41\x05\x5c\xa1\x2c\x0a\x34\x18\xe3\x97\xfc\xc3\x7c\xf1\x3a\xcb\x11\x57\x99\xaf\xb9\xc8\x9e\x38\x52\x78\xce\xb4\xb1\x88\x2a\x49\xd4\x21\xdd\xdf\xf8\x97\xf5\x0a\xb1\x8a\xfd\x1a\x4b\x02\x49\x75\x5b\xea\x6b\x34\x60\xcb\xa6\x86\xf2\x7a\x52\x0c\x4d\x31\x3c\x50\xb3\x09\xa5\x04\x92\xc2\x78\x7e\x2d\xc4\xf1\x58\x2e\xc5\xf1\xfc\x82\x85\xef\x58\x2e\x85\xef\xe2\x05\x4b\xea\xf1\x05\x49\xea\xa5\x25\x88\xc9\xc6\x14\x8e\xd9\xba\x8d\xcd\x61\xbf\x85\x9c\x25\x93\x4f\xce\xae\xd5\xdb\x75\xe1\x55\x77\xb8\x83\x6a\x20\x2d\x19\x1b\xa0\xcc\x29\xbc\xb7\xa2\x58\xcb\xc1\x79\x15\x95\x93\xf4\x22\xb9\x8c\xed\xfe\xd0\x12\x45\x69\xc1\x43\x62\x25\xad\x09\x98\x82\x23\x8f\x78\xde\x99\xae\x7d\x79\xc5\xb2\xc5\x77\x1e\x29\x94\xb7\x31\x59\xb1\x52\x4f\x4e\x13\x22\xc1\x5e\xab\xa5\xc2\x6d\xc9\x92\xae\x71\x2b\x52\x62\xb6\xfb\x63\x55\x93\xbe\xbb\xba\xfa\x15\x70\x8a\x45\x3a\xc8\x3b\xd6\x30\x3f\x44\x54\x73\x7f\x8f\xd6\x68\x65\x0e\xa4\x01\x23\xeb\x8e\x7a\xac\xa2\xfe\x0c\xd0\x89\xf7\xeb\xb0\xf7\xea\xc3\xe3\x5e\xbd\xc8\x96\xbd\x2a\xfd\xdb\x3a\xab\xd2\xd9\xb0\xb7\x68\x9a\x55\x1d\x3d\x78\x70\x93\x35\x8b\xf5\x35\xb2\x4a\x0f\xea\x55\x99\xfd\x9a\x3e\xa8\x08\x11\xff\x67\xfd\x8f\x69\xfd\x58\x7a\x7c\xda\x08\x08\x30\x1d\x05\xaa\xb4\x50\x61\x97\x56\xc6\x3e\x9d\x50\xfa\x24\xf4\x21\x20\x78\x41\xae\xb8\x16\xca\x81\x42\x42\x9b\x12\x4b\x00\xe2\x1c\x85\x2d\xb4\x00\xa5\xe3\xd0\x45\x45\x50\x78\x16\x3a\xd8\x07\xca\x68\xdc\xb6\x8e\x4b\xa1\x07\x28\x78\x12\xba\x08\x01\x0a\xbf\xf7\x60\xee\xed\x79\x6f\x6c\xc1\x82\x23\x40\x45\xd3\x8e\xc2\x26\xd4\x30\x4b\xda\xb9\xd6\xd4\x36\x83\xe8\x94\xa3\x85\xac\x6d\x95\x76\xd9\x56\x69\xe3\x5c\xf6\x56\x68\x73\x4e\xd8\xd4\xca\x09\x0b\x67\x19\xf5\x94\x52\xd5\x5d\x62\x78\x1b\x27\x1c\x78\x63\x12\x6b\x7c\xf6\x66\x86\x13\x5e\x33\xe4\xb8\x06\x6f\xe7\x3f\x1b\x34\x1d\x72\x3f\xd5\x4d\xbd\xb3\x5e\x2b\x5a\xb8\x7f\xd5\x28\x66\x2d\x8a\x0c\x34\x4b\x40\xee\x58\x9e\xa1\xa1\x5c\x4a\xf8\x3b\xa2\x56\xbc\x82\xfd\xbf\xb9\x65\x5f\x46\x89\x70\xa3\x16\xd9\xc3\x38\x99\x97\x93\x99\x2f\x65\x64\x21\x3d\x8a\x7b\xca\x50\xbd\xd7\x7c\xc1\xb0\x1b\x70\x96\xa9\x51\xc2\xfa\x51\x4a\xf3\x25\xe7\x1e\xc3\xd7\x91\x30\xb9\x7e\xc7\xe4\x44\x21\x22\x08\x75\x8c\x1e\xd5\x78\xba\x35\x6a\x81\x02\xa0\xc8\xb9\x9c\x03\xc1\x1a\x15\x68\x0c\x67\x6e\x55\x62\x67\x01\x46\x0b\x1f\xef\x8a\x4b\x73\x9f\x23\xdf\xb6\xa2\xa8\x40\x44\xfd\x6c\x94\x4d\x8e\x14\x84\x2b\xdf\x6a\xb1\xb7\x42\xc8\xce\x41\xa1\xbc\x91\x49\x24\x67\x23\xf9\xa5\xa9\x8f\x24\xc8\xd1\xa6\x82\xd4\xd1\x81\xbe\x1d\x83\x90\xee\x4c\x2e\x12\x37\x69\x10\xe2\x4a\x73\x91\xbc\x7b\x83\x30\xc1\xc4\x3c\xfa\xf6\x0c\x36\x80\x60\x5b\x37\xb6\xcf\xba\xdc\x81\xb0\xd4\x03\x61\xd2\xd2\xb7\x7f\x87\xbc\x8d\x29\x30\x23\xeb\x81\x1c\xf6\xe7\xd2\xd4\x3d\xa5\x92\xc5\x09\x4c\x45\x02\x26\x19\x46\x03\xeb\xb0\xf0\x59\xc2\xed\x18\x9a\x46\x01\xae\x5b\xf6\x53\x40\x66\x82\x5a\xe7\x05\xed\x25\x0c\xbf\x00\xfb\x8b\x1e\xa6\x5b\xec\x35\xc0\xcc\xf5\xce\x0c\xcb\xa1\xfa\x48\x90\x15\x68\x64\x96\xb4\x67\x8c\xde\xdf\x6c\xf1\x07\xdb\x22\x23\x62\x85\xab\xf8\xce\x03\x48\x98\x56\x41\x40\x08\x9b\x68\x21\x97\x31\x0d\x25\x90\xb0\xff\x98\x84\x59\x34\x92\x99\xa3\x0f\x25\x33\x83\xa3\x49\x2e\x1c\xe0\xd7\xbb\x4c\x86\x50\xaa\x25\x23\x4f\x1a\xdf\xcd\x85\xc5\x0d\x3a\xcb\x0b\xcd\x4e\xd9\x4f\x51\x22\x40\xd6\x42\x5a\x53\xd3\x5f\x61\xb2\xdc\x3b\xc3\x5e\x27\xa1\x3b\xbf\x29\x57\x98\xc5\x31\x9c\x0b\xf3\x22\x0f\xff\xdc\x69\x7d\x27\x76\xb9\x80\x96\xa5\x40\xd1\x77\xd1\x38\x97\xc6\x76\xf3\x09\x21\x44\xd8\x29\xa8\xbe\xdb\x2a\xc8\x55\xee\x3f\x48\xc8\xb5\xe5\xb8\x42\x4e\x70\x91\x5d\x92\x6b\x86\xcb\x11\x66\x97\xac\x1b\xe4\x2a\xcc\x1c\x22\x8c\x7d\x27\x74\xf3\xcc\xe2\xad\x04\x49\xd8\xfb\x2e\x38\xc9\x4e\x82\xef\x7a\x5f\x16\x69\xd1\x5b\x93\xa5\x99\x60\xe3\xe4\x1d\x7a\x14\x4c\x44\x63\xde\xde\x36\xae\x6c\x97\x4d\x22\x76\x49\x77\x05\xa7\xed\x31\x12\x69\x49\x77\x69\xe1\xb7\x9b\x82\x6c\x5b\xf8\xc3\x16\x3d\xdd\xbe\xe8\xa9\x7f\xd1\x53\x63\xd1\xd3\xbd\x16\x3d\xdd\xbe\xe8\x48\xb8\xc8\x85\x4f\x7d\x0b\x9f\x3a\x0b\x4f\x22\x96\xe6\xef\xb0\xf0\x1e\x75\xe8\x56\x1b\x1c\x0f\x6f\x42\x88\xf7\xe2\x32\x94\xb2\x33\x78\x34\x84\x67\x17\x97\x70\x96\x63\x9b\x5c\x61\x72\x41\xc7\x38\x6d\x86\x4b\xa4\x3d\x6b\xb4\xba\xe4\x27\x95\xe6\xd0\xda\x68\x29\x57\x28\xe8\x5a\xe3\xd8\x87\xaa\xa8\x19\x84\x42\x73\xfa\x6b\x7a\x8b\x16\x09\xed\x36\x30\xb4\x89\x2f\xa6\x1b\x29\x40\x09\x59\x35\x24\xc5\x42\xa4\x61\x64\xe1\x4b\x49\x6e\x26\xbd\xfb\xc6\x18\x43\x97\x4a\xda\xd6\x8e\x0a\x4d\x4f\xc4\x37\xad\x21\xa4\xda\x8e\x4c\x48\xef\x84\xeb\x35\xc5\xad\x97\x96\x17\x56\x57\xa2\xd0\x23\xa9\xd5\x1f\x00\xc9\xb3\x9e\xa6\x8e\x57\x19\x2f\xb3\xd3\xdd\xc4\x34\x22\x18\x51\x7a\x41\xd8\xa4\xe2\x72\x23\x74\xb5\x84\x69\x4d\x03\x37\x18\x96\x61\xc6\x61\x8d\x4c\x97\x6f\x5b\x0a\x61\x8a\x65\x35\x53\x97\xcb\xd4\x5a\x14\x55\xa9\x63\x6d\x76\x6d\x2d\x80\xc7\x98\xc2\x4c\xaa\x78\x2e\x14\xea\x18\xbd\x2e\x30\x5e\xcb\x48\xec\xaa\xcf\x24\xe0\xcc\xa3\xeb\x97\x3a\x30\xc9\x3f\x7b\xe0\xde\x71\x8e\x36\x3d\x02\x29\x05\xb4\x8e\x42\x85\xb1\xe2\x8f\x1a\xa4\x7a\x18\x58\x5b\x71\x6f\x0c\x73\x6d\x68\xcf\xb4\x32\xcf\xe2\x31\xb0\x1e\xad\x70\x2f\xe5\xb3\x8c\xfc\x45\xef\x0c\xf3\x14\x40\xd6\x4e\xfc\xc2\xdf\x62\x86\x90\xec\x67\x86\xd0\xe5\xd7\x56\xc8\xc0\x27\x3d\x65\x61\xa0\x6d\x00\x90\xca\x52\x42\x6a\x0f\x2a\xf7\x85\xe7\xc3\x8f\x2c\xc9\x02\xe0\x27\x12\x8a\x0b\xc9\xf9\x43\x12\xd1\xb4\x19\x7c\x68\x54\xbb\xf1\x51\x94\x36\x6c\x49\xfb\x01\x78\x9d\x1a\x29\xaf\xe8\xf3\xa6\x3f\xc2\xec\x2f\x9f\x56\x2b\x99\xfd\xe5\xa4\x61\xa2\xb9\x3f\x16\xad\x68\x8b\x78\xdf\x34\x30\xde\xbf\xd9\x17\x21\xf0\x42\x28\x50\xbb\x8c\x48\x30\x16\x03\x73\x81\x8d\xc9\x05\x02\x28\x03\x1f\x88\x2b\x59\x29\x5b\xee\x62\x63\x88\x93\x60\x3d\x38\xa3\xe1\xa9\x30\xde\x39\x2d\x8b\xfc\xd6\x10\xf8\xb5\x44\x30\xb6\x97\x98\x6a\x49\x8c\xd2\xb0\xee\xf2\xce\xcd\x13\xd2\x1e\xd7\x23\xe5\xf4\xac\xde\x00\xf7\x3c\x1d\x6c\x5c\x10\x94\x9e\x20\xb3\x42\xdc\xcd\x3c\x1f\x1a\xf1\x91\xd9\xab\xb5\xd3\xd1\x19\x46\x0a\xf3\x4d\x16\xde\x50\xb0\xac\x87\xbb\xd2\x3b\xa8\x2b\x8e\x45\x29\xa4\x27\xc2\x58\x67\x79\x39\x4b\xea\x85\xc8\x00\x3d\x7c\x50\x97\xd3\x5f\xd3\x86\x13\x3f\x57\xb6\x90\xae\x7f\x41\x1c\x4d\x10\x06\xab\x04\x73\x6b\xc2\xac\x3f\x67\x98\x58\x33\xf8\x35\xc3\x8c\x96\x98\x1a\xe2\x13\x06\x42\x45\xf7\x3c\x94\x03\xb4\x7e\x3c\x47\x2f\x39\xf8\x8d\x72\x78\xf1\x12\x20\x15\x9f\x6a\x7e\xfc\x58\xae\xb2\x29\x3f\xbe\xc1\xe0\xf2\x21\x0c\x2f\x41\x8d\xe3\xa4\x24\x59\x64\xfb\x62\xe0\x55\x1c\xd6\x78\x21\x8a\xe1\x01\xf4\x57\x9f\x81\xd4\x4f\x43\x54\x1b\x15\x70\x24\x51\x53\xbd\x41\x27\x5f\x18\xf7\x8e\x26\x78\x6a\xdd\x4d\xf0\x9c\xbd\x8d\x90\x97\xa1\x68\x46\x2e\x8d\x6c\xa8\x90\x0d\x41\x93\xb0\x2b\x95\x6c\x0e\x57\x6e\x67\x63\xbc\xbc\xdb\x9b\xb2\x13\x8a\x19\x3b\x19\x9d\x3d\x7e\x1c\xf2\x26\x47\x4f\x42\xde\x7c\x00\x1a\x8a\x3d\xfd\x70\x57\x9c\x34\x1f\xd0\xb4\xa1\x02\xf6\x9d\xb6\x15\x76\x8d\xa0\x02\xde\x53\x24\xbb\x30\x98\xa5\xf2\xf9\xd2\x0d\xd7\xed\x8c\x64\xef\x28\xd8\xbf\x05\x7c\x71\x39\x19\x4e\xe1\xdf\xeb\x0a\x40\x6b\x8a\x52\x12\x1c\x33\xc6\x0d\x0f\xd0\xb1\x76\xb9\x4c\xa8\x12\x4c\xe6\xcf\x55\xb2\xfa\x73\x36\x6b\x16\x0c\x80\xf8\xf5\xce\xbd\x82\xbd\x69\xcc\xbd\x6a\x4a\xd8\x26\x91\x3f\xe6\xb7\xec\xd4\xde\x91\x99\xb7\xee\x14\x5c\x56\x78\x7e\xa7\x79\x89\x1a\xed\x1d\x5b\xb2\x77\x42\x87\xad\x5d\x16\xc9\xe7\xec\x06\x73\x73\xed\xea\x6e\x57\xac\x60\x5f\x77\xf6\xa6\x77\xec\x39\xe6\xd2\xa0\x0d\xc5\x87\x97\xc0\x49\xc0\x8f\xa6\xbc\xb9\xc9\x53\xb9\xaf\xf8\x62\xe7\xce\xca\x86\xe4\xde\x36\xc6\x39\x5c\x2d\x2a\xb8\x2d\xa3\x62\xf7\xfe\x3a\x93\xde\x95\xed\xe1\x1b\x27\x2d\x65\xd3\x70\x02\xb3\x5a\xff\xf8\xb2\x28\x33\xc4\xb4\xc9\x97\xe4\x96\x41\xfc\x17\xc6\xdc\x1a\xcb\x8a\xca\xbb\xe1\x5c\x36\xaa\x97\xa3\x80\xb6\x04\x4e\x42\x04\x1f\x15\x43\xf9\x88\xee\x52\x2a\xd1\x09\x20\x71\xf1\x08\x8b\x91\xe4\xa2\xaa\x7c\x24\xcf\x2a\x40\xb7\x70\x61\xe6\x18\x14\x6b\x1c\x8a\x0a\xfc\x52\xa0\x4d\x3d\x2b\xcf\x40\xf5\x20\xff\xb6\xce\xcc\x11\xf2\xb7\xb4\x08\x3b\x6e\x01\xb1\x50\xfa\x1a\x30\x71\x36\xae\xde\x8e\xef\x79\x81\xf5\xe7\x16\x02\x20\xd3\xb2\x5f\xba\x10\xbf\x6e\xa4\xb0\xd0\x7e\x0a\xf7\x7f\xfa\x25\xd8\x07\x87\x38\x30\xb6\x2b\x12\x72\x17\x6a\x1d\x3e\xa8\x80\x80\x44\x61\xa8\xef\x54\x61\x7a\x59\x32\x05\x6a\x85\x04\xe5\xaf\x22\x40\x20\xee\x48\xf6\x0e\x3e\xaa\xb0\xba\x50\x34\x92\x6e\xbf\x7e\x20\x0e\x9c\x36\x6a\x61\x13\x21\xf3\x45\x62\xbf\x10\x0b\xaf\xf3\xb7\xc9\x17\xbc\xaa\x3a\x73\x9b\x2c\x6f\x92\x6b\xca\x3a\x25\x2e\x82\xb6\x7d\xb6\x66\x96\xa6\xb1\xa6\x8d\x49\x53\x01\x0d\xf5\x48\x74\x3c\x45\x27\x32\x2b\x89\xe2\x44\xc8\xfe\x73\x21\xf2\xa7\xbd\x8d\xa6\x17\xe3\xcb\xe3\xe3\x5a\xc2\x43\x1f\x7f\xeb\x48\x83\x54\x91\x40\x38\xaa\x0d\x88\xef\xdb\x15\x88\xe6\x11\x2d\xf5\x99\x4a\xea\x5f\xe0\x4f\x6c\x29\x5c\x0f\x79\xa7\x30\x5e\x10\x94\x0d\xac\x4f\x89\xd6\xa1\x4f\xcf\x99\x36\xd2\x1f\x46\x29\x66\x2e\xe0\xb2\xd4\x1d\xd3\x12\x76\x77\x6a\xb0\xc5\x89\x00\xd8\xff\xf6\xfc\xc5\xc7\x9f\xde\xfe\x82\x26\x19\x7a\x61\x68\x40\xb8\x2e\x27\xc1\x7f\x0b\xcc\x40\x8a\xd4\x54\x43\x04\x5f\xc4\x66\x60\x19\x72\x5e\x44\x02\xc2\x70\xd3\xc1\x64\x75\x9e\x50\x00\xaf\x8e\xdb\x74\xb5\x19\x44\x98\x58\x1a\xaf\x6e\x74\xcb\xef\x51\x63\x3d\xa2\x42\x0a\x3b\xb8\xa3\xa4\xc7\xc4\x3a\x4d\x2f\xce\xe0\xdf\xe2\x5c\x92\x73\xbc\xf0\x58\x8a\x53\xe7\x3a\xb4\x00\xe6\x6b\x77\xe8\xbf\x1a\x5b\x48\x95\x7f\x55\x5b\xe8\x56\x5d\xd6\x37\x01\x06\x8c\x54\x8b\x76\xc6\x10\x34\x8f\xa9\xfa\x22\x96\xeb\x75\x66\xac\xd7\x44\x2c\xeb\x22\x9c\xa3\xfc\xd1\x68\xae\x06\xe4\x62\x35\x37\xe6\xe6\x74\x3b\x63\x6f\x3b\xa9\xd3\x0e\x63\x39\x05\x85\xf4\xd3\x07\x83\x84\xcd\x00\x06\xf1\xaf\xef\x3d\xe6\xc1\x0b\xf4\x56\x5c\x54\x43\x4e\x93\xd0\x0f\x48\xab\xd9\x7b\x2a\x8e\xe7\xb3\xde\x69\xef\x5f\x48\x35\xd8\xd3\x07\x36\x78\x80\x50\xd6\xbb\x10\x25\x97\x50\xe7\xe7\x14\x25\x8c\x98\x83\x8f\x12\xf7\x15\x0d\xda\xec\x20\x37\x84\x5a\x2e\xf9\x65\x68\xf4\x82\xa7\xa9\xf7\x14\xff\xc5\x2e\x5e\x90\xb1\x58\x8f\x8e\x18\xb6\x8f\x47\x08\x8a\x5f\xaa\x13\xc4\xda\x48\xb3\x7d\x81\x0d\xcc\x36\x97\x69\xef\xa9\x80\x34\x6c\xf4\x43\x8a\xb9\xff\x58\xa0\xa7\x91\x4a\xf0\x80\x61\x0e\xde\x2f\x80\x85\xe3\x1f\x32\x81\xa0\x6c\xdc\x37\x62\x80\x88\xde\x53\x4e\x45\xff\xac\xdd\x8f\xcc\x37\x48\x4e\xd6\xa9\x3b\x75\x5c\x8d\x35\x27\xd2\x30\x5a\x04\xa0\xd8\xd9\x90\x31\xa2\x86\x46\x8f\x3b\xda\xbb\x10\xb5\x2e\xe9\x2b\x5a\xec\x69\x9e\xa2\x40\x04\xdf\xca\xc9\x5e\xd2\x99\xda\x6c\x84\xf2\xdd\xc5\xbc\x80\xee\x49\x0b\xee\x22\x5e\x28\x3f\x0b\xdb\x78\x17\x8a\x9f\x84\x0e\xda\x85\x32\xd2\x6a\x3b\xc8\x1e\xae\xb4\x27\x8a\x2c\xa6\x6b\x64\xbf\x5c\x92\x74\xa1\x51\x7c\x69\xbe\x45\xd4\xed\x56\xaa\x57\xa7\x74\x55\x55\x74\x6d\x94\xc3\xf7\xf8\x83\x03\x6d\x57\x18\x6c\x61\xf8\x0b\x93\xae\xd0\x8d\xbc\x25\x3e\x26\xd7\x28\x62\x1e\xfe\x67\xfd\x55\x29\x0e\xf5\x24\xe4\x75\x99\x8b\x72\x96\xeb\x3e\x58\xad\x49\xa3\xb8\x52\x74\xda\x8b\x1c\x08\xa0\xfe\x1d\xa0\xf4\x55\x9e\xdc\x92\x29\x75\xf0\x7c\xb5\x0a\x42\xfe\x20\xba\xc8\x43\xb4\x0b\x53\x1a\x88\xe9\x50\x12\xd1\xa1\x26\xa7\x07\xb0\x21\xe2\xd9\x75\xf4\x64\xb7\x09\x91\x6d\xe0\xcf\x59\xb3\x40\xe5\xbd\x88\x6a\x96\x14\x35\xa5\xaf\xfc\x48\xde\x45\x70\x41\x17\x33\xdb\x41\x4e\x59\xb4\x7a\xf2\xe8\x50\x12\x81\xd0\x7d\xb5\x0e\x39\xc3\x80\x5b\x9e\x70\x39\xc2\x8c\x41\x24\xac\x04\xc1\x62\x2f\x1a\x51\x0b\xee\x9a\xc1\xce\x93\x15\x87\xb9\xea\xd1\xd9\xa3\x1f\x43\xda\xbc\xe8\x6c\xf4\x63\x68\xef\x63\xf4\x68\xe4\x90\x1c\x8f\x0e\x10\x8b\xec\x0f\x2b\x04\x0b\x80\x66\x9a\x8f\x59\x93\xa7\x02\x1a\xa4\x79\x1a\x73\x13\x5c\x26\xc0\xe6\x0d\x1f\x86\x3f\x96\x5f\x2d\xc8\x91\xe5\x3f\x15\xab\xb5\x84\x29\x11\xdf\x1e\x65\x22\x06\xa4\xad\x24\xd1\xcf\x47\x83\xef\xf4\x74\xf6\x11\x89\x15\x11\xdd\xde\x21\x61\x44\x70\x7b\x17\x08\x67\x5b\x81\xf0\x05\x31\xaf\x12\x0a\x17\x40\xa9\x92\x07\x04\xc0\xa2\xa4\x3d\x56\x61\x60\x75\x7e\x69\x6b\x67\xda\x2e\x1c\xf3\xfe\x91\xc8\x22\x86\x3c\x06\x86\x59\xd4\x9e\x86\x78\xdd\xbf\x4b\xaa\x64\x59\xf7\xd9\x62\x9d\x0e\xfc\xf9\x5c\xd2\x2c\x18\x07\x0b\xb1\x45\x18\xfc\x63\x70\xa2\xde\x0f\x22\x59\x7e\x7c\xdc\xaa\x8a\xa2\xb3\x36\x4c\xdb\xfe\xff\x38\xa5\xa1\x31\x0b\xa5\x92\xc1\x64\x78\x62\x0c\xd0\x23\x86\xbe\x95\xbf\x81\x9e\x3b\x27\xd6\xfe\x74\x55\x65\x9f\x29\xd3\x34\xff\x54\x48\x8a\x7f\xea\x7b\xc4\x77\x7a\xee\xa6\xb8\xe6\xc2\x75\xa2\xeb\xb8\xb4\xca\xeb\x8e\xf2\xae\x63\x37\xed\x28\xcf\xbd\xc7\x71\xe6\x1c\x47\x03\x11\x7b\x0f\xa3\x17\x06\xa3\xb3\x27\x84\xe4\xed\x23\x01\x47\x95\x4c\xa0\x1c\xe8\x87\xe2\x87\xa1\x0f\xf8\xe1\x05\xd9\x3e\x19\x27\x08\x8a\xe8\x4a\xb0\x8e\x03\x8c\x64\x7c\x08\x0a\xf8\x96\x04\x70\x77\xc6\xf4\x80\xb5\xc5\xeb\x76\x4a\xb0\x4d\x40\x4b\x12\x4b\x0d\x9e\x1a\x34\x87\x75\xf6\x5f\xc0\xbf\x22\x19\xc0\x35\x99\x9a\xf5\xd4\xdc\xe8\xdc\x36\x12\xf3\x94\x16\xe6\x21\x2c\x93\xac\x9b\x12\x73\xb8\x09\x5b\x7d\x0b\x09\x68\x12\x6a\xbd\x0d\x3b\xb8\x97\x94\x62\x7c\x72\xe7\x85\x6e\x6f\xd5\xfa\x84\x24\x1f\x6d\x4c\x23\x0e\xc3\x0b\x26\x27\xba\x30\x4e\xb6\x03\xe3\x10\xc4\xd8\x68\x47\x5d\x7d\x75\x18\x48\x09\x2c\x93\x75\x33\x5c\x28\xfd\x7e\x6d\xe1\x23\x55\xe5\x32\xdc\xed\x18\x89\x86\x6c\x37\xd2\xc7\x6b\x80\x7a\x66\xbb\x23\xd7\xb0\x46\x3b\x84\x89\x90\x07\x2d\x44\x82\x8d\xb4\x47\x63\xb9\x2d\xb6\x1a\xc2\x6f\x16\x44\x73\x10\xd5\xfb\x22\x47\x21\x8a\xd7\x2f\xdb\x83\xb8\x1a\x13\x5f\x51\x7c\x38\x03\x5f\xe5\x82\x7d\x53\x85\xe8\xfb\x23\xb0\x64\x34\x1f\x92\x0c\xd0\x07\x99\xc0\xda\x19\xcc\xa6\x46\xac\x07\xe3\xd5\xb0\x40\x63\x1d\x80\x5e\x73\xb9\xe8\x6c\xdc\xdf\x07\x80\x0d\xd1\xc0\xf4\x6d\x95\xdd\x64\x45\x92\x7f\xe4\x04\xb7\xda\x97\x79\x17\x32\x7e\x41\x22\xcc\x28\xa0\x55\x83\xbf\x2f\x0d\x39\x57\xd6\x4d\xbb\xf8\x5f\x19\x88\x99\xf1\x78\x83\x20\x79\x7a\x9d\x54\xc1\xa6\xfd\x49\xbd\x4a\x8a\xae\x6f\x02\x94\xcd\xa0\xa8\x6a\xb0\x77\x57\xb8\x20\xa7\x5f\xaa\x64\x75\x48\x5f\xac\x27\x99\x21\x80\x01\xe2\xab\xf3\xdb\x0f\x46\xd2\xb9\xe8\xee\xea\x6a\xd1\x2c\xf3\xa8\xd8\x60\x82\xbb\x56\xa3\x99\xdd\x62\x06\x0b\x77\x2a\xa5\x9b\x34\x8b\x28\xf8\x20\x7e\x96\x05\x43\xe4\x6a\xc8\x12\xd3\xcd\x9e\xcd\xe5\xe5\x0d\xe0\x63\x8c\xfe\xd0\xe0\x2f\xda\x24\xd1\x76\xa3\x1a\x25\xb0\x70\x81\xdf\x3b\xe2\xd6\xd2\x21\x42\x46\x24\xd0\xb5\x47\xbe\x31\x11\xcf\xe4\x9b\x40\xc7\x22\x2b\xa4\x1f\x6c\x8c\x00\xc1\x43\x55\x7c\x7f\xcf\x17\xea\x8e\x1b\xd5\xe1\x90\xfc\xd8\x13\x5e\x3e\x0c\x3d\x38\x17\xca\x1f\x87\x1e\xf4\x2d\xf8\xa7\xed\x57\xb4\xc5\x41\x6d\xbb\xba\xf5\x35\x13\x9d\x19\x37\xab\x73\x8f\x1e\xa0\xa2\x31\x48\x69\x25\xca\x2b\xbb\x2e\xa2\xa4\xf3\x22\xaa\xbd\x37\xca\x7a\x3b\x0d\x2b\xb1\x80\xbc\x4f\xea\x3d\x2e\x83\xbb\x1a\xd8\xf7\xb7\x64\x4c\x97\xe4\x35\xc6\x34\x96\x58\xf9\xc3\xfa\xda\x0a\xb3\x43\x96\xc7\xab\x8a\xb4\xb3\x22\x7c\x9b\x88\xcd\x4a\x31\xe0\x89\xa3\x47\xa1\x15\xac\x73\xcd\xf1\x08\x30\x7c\xc3\xb2\x8f\xe6\x7e\xea\x3d\x8a\x26\xec\x97\xe8\x34\x31\x27\xcb\xf1\x7e\x36\x5c\x26\xab\xbe\xaa\x2b\x6f\x25\x51\x5f\xc8\x19\xc3\x80\x12\x8e\xc2\xc7\x03\x72\xe2\x23\x21\xb9\x6e\x1f\x7e\xd9\xed\xa3\x48\x5d\xbd\xae\xeb\x1c\x9a\x4d\xa7\xbf\xa6\x33\xe1\xc8\x2c\x70\xb7\xb9\x08\xc7\xc7\xfd\x5a\x49\xe5\xf5\xd0\x65\x89\xdd\x7c\xad\x44\xfd\xba\xa6\x2c\x71\x6b\x4a\xe9\xbf\xae\x29\x4b\xac\x9a\x68\x84\xa3\xc2\x88\x0c\x83\x01\x86\x18\x2f\x48\xc4\x29\xaf\x26\x34\x16\xa9\x91\xce\xd5\x31\xc8\x13\x16\x7b\x55\x61\xaa\xef\x55\x94\xcc\xb4\xae\x55\xfb\x1e\x76\xb7\xbf\x6b\x4d\x36\xdd\xb7\x20\x65\xd9\xb3\x42\x25\xf9\xd7\xb4\x89\x0f\xe0\xac\x83\x0c\x89\x63\x40\x4d\x85\x42\x7a\xf8\x04\x98\xf4\x76\x05\xbf\x31\x63\x4c\x10\x12\x97\xbf\x28\x73\x1c\x55\xf0\x49\x56\xd9\xb4\x19\x00\xa7\x35\xb9\xea\x5b\x5a\x7b\x27\xab\xec\x6e\x4d\xc2\xc5\x96\xd6\xde\xcb\x2a\x80\xe2\x3d\xed\xb5\xaf\x47\x71\x92\xdb\xac\x52\xc0\xda\x5a\xd4\x20\x46\xe2\xb9\xfd\xdd\x29\xbf\x28\x0b\x71\x84\x8d\xdb\x86\x4b\x3c\xed\x2e\xc6\x62\x27\x14\x1a\xd9\x39\xf1\x1d\x93\xfe\x85\x5e\x8b\xa4\x41\xff\x46\x71\xaf\x83\xd7\x55\x9a\x62\x6e\xbe\x3d\x96\x55\x60\x92\x2d\x1d\x3c\x97\x35\xec\x3e\xb2\x6a\x3a\x9c\x8b\x7e\x86\x45\xda\xec\xd1\x17\xeb\x9b\xba\x67\x82\xaf\x77\xb7\x22\xf1\xd5\x96\x96\x5e\xc8\x2a\x98\xa9\xa7\xdd\xde\xaa\xeb\x34\xe4\xe8\x0c\xbc\xdf\x51\x01\x14\x27\x07\x40\x98\xee\xba\xfc\x8a\xbd\x05\x1f\x3e\xfc\xec\xdd\x52\x0f\xb9\x90\xe6\x79\xb6\xaa\x51\x0d\xe8\xa1\x57\x14\x52\xd9\xf8\x40\x59\x8e\x85\x07\x50\x13\xb4\x05\x21\x47\x3d\x57\x90\xb5\x69\x51\x0e\xeb\x7d\x29\x87\x9d\x44\x80\x61\x45\x20\x2e\x73\xba\xc1\x0f\x30\x22\xf0\x0b\xc3\x5c\x8b\x0b\x66\xbd\xb3\x62\x8e\x96\x9f\x98\xbc\x03\x2e\xf3\xbe\xcb\xb7\x9a\xa2\xae\x3f\xa5\x09\x80\x00\x4b\xb5\x94\xc8\x4c\xbc\xfb\x19\xf3\xc4\x98\x72\x33\x45\xb0\x2c\x75\x05\x83\xa3\xf5\xb2\xbb\x2e\x57\xab\x65\xf5\x2b\x2f\x31\x31\xdf\x4a\x4c\x68\xd1\x85\xa6\x27\x56\x86\x38\x0c\xd8\x4f\xd1\x01\x39\xde\xab\xf2\x69\x4b\x4c\xb6\x9b\x04\x59\xa4\xd9\xcd\xa2\x89\x84\xb4\x8c\xb3\x78\x53\xd1\xe9\x78\x34\xda\x15\x2a\x45\x7c\x05\xe8\x82\x2c\x06\x55\x7c\x3d\xb4\xca\xc9\xfe\x0b\x11\x94\x86\xdd\xf7\x54\xd4\x65\x58\xdd\x6e\x94\xed\xb7\xbe\xb9\xdd\xd5\xcc\x99\xaf\xc1\xd2\x02\x68\xb1\xc1\x37\x72\xe2\x2f\xdf\xbe\xc1\xd4\xea\x7d\x91\xb3\x02\x61\xe8\xc3\xb4\x2a\x73\x8c\x1e\x51\xd3\xc3\xc7\x72\x75\xd2\x60\x7a\x26\xb8\xb9\x79\x6d\x88\xe9\xe5\x97\x5c\x60\xaf\x53\xbb\x73\x19\x93\x60\x4d\x6f\xc8\xba\x47\x46\x07\xd0\x1d\xee\x35\x46\x3d\x26\x77\x08\x92\xf2\xe0\x05\x69\x91\x1d\x9e\xae\x35\x25\xb2\x1d\x0a\x60\x71\x8d\xaf\x0f\x5a\x54\x23\xbd\xbc\x58\x41\x6a\x63\x22\xe2\x02\xce\x38\xb8\x29\x52\x28\xaa\x20\x6e\xc2\x7c\x68\xda\x41\xb1\xb8\xa2\x8b\x02\xea\x90\x02\xa4\x5a\x2c\x81\x51\x26\x85\xbc\x01\x33\xa9\x78\xc8\x25\x79\x9a\x3c\xd6\xce\x3a\x69\x89\x6c\xe4\x24\x3d\xc9\x26\x22\xb1\x47\x5b\x9a\x7a\xf7\x6b\x7a\x1b\x95\xa6\xe9\x85\x19\xb6\x64\x4c\x11\x4b\x00\x47\xe9\xc8\xe4\x18\xae\xa4\xa3\xb5\x5a\xb4\x76\x12\x9c\x06\x27\x6b\xbe\x58\x38\x59\x78\x88\x4d\x44\xa2\xa5\x8b\xf5\xe5\x86\x6c\xf4\x31\xc8\xad\x0c\x83\x72\xbe\x9b\xd2\x11\x63\xa4\x4b\xaa\x75\x9b\x94\x82\xce\xc1\x1d\x0d\x30\x4d\x46\x93\x64\x0a\x2a\x22\x63\xed\x18\x74\xc2\x94\xbf\x13\xef\xcf\x1e\x6d\x00\xcd\x63\xba\xa4\xdf\x34\x08\x51\x5d\x0f\x84\x5a\xb5\xaf\xaf\xb9\x73\x7d\x39\x2a\xc0\xed\xbc\xaa\x89\xe2\xe1\xdd\x8f\xbb\x44\xcd\xed\xfb\x04\xa6\xfa\x28\xf4\xdc\x26\x50\xfe\xc4\xe6\x70\xdb\xb7\x63\xe8\xde\x64\xd1\xf8\xa1\xcb\xfe\x1e\x60\x0e\x27\x2f\xcf\xbe\x79\x7b\x3a\xd7\xa2\x66\x88\xd1\x34\xdf\xc3\x06\xdb\xc2\xd5\xda\xab\xe4\xd9\xce\x0a\x5b\x6b\x14\x08\x0f\x95\x17\x12\x3d\xba\xb8\xd1\x34\x06\x17\xbb\x21\xa0\x7a\x74\x29\xd3\x12\xa1\xbf\x4f\xdd\x7a\xab\x38\x2d\x42\x0c\xdb\x44\x98\xd6\xf7\x93\x64\x88\xf6\x88\xa6\x0c\x12\x15\xf3\x14\xe2\xda\x51\x00\x89\x37\x3b\x70\x8f\xd5\x3a\xe0\x1d\x22\x14\x8b\x58\x42\x76\x40\xe1\x01\x58\x20\xa9\xc6\xbe\x4b\x0c\x49\x1d\x03\x56\x4c\xdb\x7c\x1b\x8b\x8d\x98\x5d\xe8\x79\x74\x3e\x6d\xb1\x92\x18\xc8\x69\x4d\xb3\xf0\x13\x96\x7a\x0d\x37\x72\xda\x18\x9e\x9c\x90\x0d\xfa\x77\x9c\xc4\x81\xd4\xc9\x9f\xa2\x56\x0c\xcb\x3d\x24\xe8\xca\xea\xb9\xf0\x9c\xe8\xee\xe1\x35\x19\x32\x69\x61\x39\xc4\x07\xc0\x2d\x4b\x12\x47\xc0\x33\x32\xe5\x9d\x0d\xed\x12\x46\xc2\x1a\x9d\x24\x28\x90\xdc\x4e\xf4\x6e\x95\x8a\x59\xda\x29\x3a\x37\x80\x0f\x1e\xed\x29\xbf\x3a\xc0\xc0\xb4\x53\x15\xac\x91\x12\xd1\xf8\x7f\xca\xf0\xd7\xad\x71\x7a\xbd\x44\xa9\x7b\x78\x35\x51\xba\x76\xde\x38\xad\xba\xca\x9b\xc6\xa2\x71\x0f\xb1\x2f\x30\xb5\x6d\xa6\xa1\x81\xa6\x59\xcb\x30\x58\xa8\x8e\x2d\xeb\x03\x9e\x4c\x18\x40\xef\x1f\xc4\xbc\xf6\x23\x69\x05\xc7\x13\xec\xa2\x5e\x35\xd9\x42\xf3\x77\xe8\x96\x72\xba\xae\x31\xcc\xbd\xd1\xfd\xe1\x1f\xf3\xe9\xfa\xd7\xd4\xce\x01\x01\xd4\xe0\xf8\x21\xd1\x90\x5f\x16\xd9\x74\x81\xce\x78\x42\x26\x45\x43\x57\x49\x22\x0c\x45\xd1\x24\x78\xc0\xaa\x16\xb3\x22\xaa\x24\x6a\x69\x33\xd8\xb7\xdf\x85\x4a\x71\x81\x6e\x65\x42\xff\x52\xb3\x4d\xd6\xee\x9a\xe1\x9a\x73\x58\xda\xe3\x82\x52\x32\xb7\x6f\xd3\x8f\x6a\xc9\x85\x2f\xd2\xc3\x1f\xf4\xf4\xce\xfb\x6d\xd1\x25\xb4\xa4\x0c\xf6\xfb\x40\x27\x3c\x1a\x19\xf5\xd7\x43\x65\xc0\xdf\x1f\x44\xc1\x1f\x93\xe9\xaf\x70\xd8\xa7\x29\x2f\x00\x50\x44\xf7\xf7\xc1\x4b\xca\xb5\xaa\x4a\xce\xd5\xc8\xa2\xe0\x53\x91\xcd\xe0\xd3\x6c\x9e\x01\xc0\xc8\x0a\xc7\xc7\xaa\x86\xdc\x15\x56\x94\x6d\xd1\x93\x89\x59\xd9\x8b\xe0\x17\xc6\x6d\x35\x5f\xf1\x21\x3b\x02\x1a\xa9\x7f\xe9\xe4\xe4\x89\xf0\x11\x3f\xba\x1a\xb1\x25\x1e\x62\xc8\x06\x79\xc6\x87\x8b\x83\x74\x8b\x32\xde\xf6\xb2\x00\xb8\x7c\x59\x7e\x29\xcc\x8b\x00\x8a\xf0\x7e\xe0\xa5\x31\xca\xb9\xa4\x85\x46\x5d\xb3\x1a\x0b\x91\x00\xca\x1c\x87\x5b\x49\xb3\x83\xd5\xff\x4e\xfb\x8f\xbf\xdf\x4a\xb0\x75\xe2\xe4\x03\xec\xdf\x0d\x9c\x6c\x89\x17\x4a\x2f\x36\x4c\xf6\xc1\x86\x44\x6d\x2a\x64\x58\x5e\x76\x92\x17\x99\xa1\xc7\x64\x2a\x03\xe9\x87\x0e\xda\x01\x28\x0f\x4d\x72\x14\xf1\xdd\x0a\x0e\x70\x56\xdc\xfc\x9c\xce\x15\x5f\xb7\x94\xd8\x18\xcf\xc7\x49\xb0\x02\x92\xdb\x62\x86\xb8\x0f\x71\xe5\xa7\xce\x95\x6f\x57\xd8\x79\xf7\xa7\x61\xdd\xdc\xe6\x5b\x69\x80\x5d\x57\x77\xd3\xbe\xb6\x13\x01\x6f\x2d\x18\xf1\xdf\xc5\xb4\xd9\x07\x18\xa2\xef\x21\x7e\xfa\x07\x93\x7a\xf6\x5c\xc0\xc2\x66\xa1\xde\x76\x31\xbb\xd7\xaf\xfa\x6a\xea\x05\xaa\x7c\x2b\x50\x49\x9d\xa9\x84\xa7\xa9\x71\xb9\x26\xd2\xff\xc4\x12\x13\xd5\xdd\xd6\x54\x1e\xe1\x05\x19\xf7\xa1\x4f\x31\xdb\xc7\xa0\x66\x41\xc4\x38\x94\x4c\xb7\x5b\xbe\xe7\xad\xe8\xc1\xbf\x3a\xe3\x82\xc7\xec\x40\x5d\x53\x88\xcb\xb9\xd7\xbe\xbc\xb0\x8c\x3b\xcc\xb9\xb3\xba\x89\x77\xb9\x8c\x91\x7f\x32\xe7\xc1\x75\x5e\xa2\xad\x75\x50\xa0\xf3\xce\xc6\x35\x38\xa0\x8a\x15\xc5\x33\xad\x49\x77\xe6\x61\x69\xbc\x67\x04\x59\xfa\x66\x98\xcd\x6c\x52\x17\x3d\x43\x5f\xe2\xad\x33\x4e\x1f\xfe\x41\xd1\xbd\x48\xe1\x33\x39\x2e\x1e\x91\x11\x87\x96\x8c\xf0\xeb\xbb\xef\x1c\xa9\x64\xe7\x03\xe9\x53\x40\xec\xb8\x6f\xb8\x01\xdf\x75\xb3\xed\xaa\xd8\x43\xd7\x22\x1a\x16\xab\x88\x6b\xec\x1e\xf8\xdc\xb9\x60\x5c\x05\xf5\x76\x5b\x31\x51\xf7\xc9\x78\x07\x5f\x6f\x52\xf5\x1e\x36\xdd\xb9\x3d\xf6\xf6\x27\xd1\x08\x65\xfb\x01\x6e\x1a\x40\xd4\x75\xf0\xbb\x98\xc5\x1a\xca\x24\xd5\xb0\xbb\xa8\xec\x06\x67\xe2\xc8\xdf\x6c\xdb\xdc\x72\x8a\x94\xe6\xb3\x3f\x35\xe9\x52\x0a\xde\x1d\x64\xd9\xd6\xb8\x8b\x17\xb6\x0c\xa2\x65\x67\x26\x14\xf8\xbf\xa7\x1d\xb4\x18\xac\x9f\x45\x21\x6b\x2f\xec\xd4\x96\xb6\x27\xda\x48\xcc\x45\xaf\xc6\x04\x6a\xc4\xaf\xe2\x60\x70\x85\x96\xa4\x42\x1b\x5a\x6b\x07\x37\xad\x47\x16\x9b\xb8\xf5\xab\x5a\xed\xf4\x76\x59\x45\x98\xfa\xe5\x9f\x4a\xdb\xdf\x0e\xe4\x81\xf2\xcf\xd4\x2f\x9e\x2c\x19\x97\x65\xa1\x70\x94\xc9\x94\x6b\x22\x8b\x40\xd8\x38\x40\xe2\x4b\x5a\x40\x0e\xda\xde\xbf\xc8\x42\xd6\x60\x62\xb0\x08\x74\x9c\xf7\xc8\x5d\x8b\x9d\xfd\x9e\x14\x9e\x9e\x85\xe3\x1e\x0b\x44\x65\xef\xe6\x7e\x60\x58\x92\x7e\x86\x71\x7a\x7d\x2f\x61\x7c\xf0\xd2\x1b\xf5\x62\xd7\x68\x9a\xf6\x68\x1a\xb1\x08\x34\x9a\xbd\x30\x22\x26\x26\x66\x41\x67\xab\x2e\x5b\x35\xd9\xd5\x85\xa5\x93\xb2\x41\xf3\x88\x76\x4c\xa8\xdb\x6c\xd5\x30\xfb\x06\x73\xaa\x24\xbf\x84\x9d\xf7\xc1\xe9\xc0\x7d\x9d\xf2\xb8\x6a\x2f\x6f\xb3\xc5\x46\x6a\xaf\xca\xd3\xf2\xa6\x43\x86\x65\x9c\x94\xb6\x9a\xf3\x70\x0f\x80\x9d\x16\x4d\xb6\xd0\xe8\xc9\x28\x6c\xa3\x29\x28\x7e\x18\x7a\xb0\x21\x34\x35\xda\x7d\xd5\x3c\xfe\x3d\xfc\x08\xba\xa8\x50\x57\xf2\xdb\x58\x42\xa3\x43\x8c\x9f\x8c\xc9\x19\x06\x50\xb6\x90\xa7\x61\x4a\x53\xc0\xa4\x8b\xcc\x12\x25\x7b\xd5\x6c\x86\x14\xc2\xea\x12\x65\xc5\xdc\x89\xe4\x1c\xec\x66\x7d\x86\x6a\x20\x3a\xc1\x04\xd7\xea\x1a\x69\xf5\x28\x12\x5d\x4a\xcb\xd1\xe4\x5a\xd9\xfd\xb7\xdb\x6c\xd7\x55\x34\xaa\xec\xac\x56\xb2\xab\x5d\x2c\x53\xa3\xbd\xe7\xbc\x07\x59\x48\x67\xf5\x20\xc8\xe2\x73\xbb\x5c\xf3\xdb\x0d\xeb\x3b\x61\xf2\x80\xe8\x0d\xdf\xae\xce\xb7\xdc\x51\x34\x0d\xf1\x1b\xad\xd1\x0f\xe1\xab\x64\xe7\x36\x67\xb5\xdd\x44\x3c\xfb\x6d\x26\xe2\x0c\xc3\xa6\x7d\xb8\x4c\x07\x8f\x08\xb2\xde\xe1\x05\x10\xda\xce\x03\xff\x3f\x52\xec\x77\x5b\xc8\x6f\xb7\x53\xb7\xa5\x79\xfb\xac\xe1\xe6\x50\x5b\x7a\x8f\xc7\xc6\x3e\x7d\x6c\xd5\xd4\x1f\xa0\x96\x3f\x58\x29\x8e\x99\xb3\xad\x78\x70\x0a\x5f\x79\x6c\xf9\x1d\xf3\x63\x7f\xac\xb8\x0e\xb2\x28\x91\x8c\x2e\xda\x77\xa9\x40\x06\x98\xc6\xb3\x18\x8a\x73\x16\x33\x67\x1d\xa6\xca\xa1\x78\x0f\xa5\xb5\x34\xc1\x0e\xba\xe5\x4b\x40\x91\x7d\x8b\xbe\x3a\xdd\x4b\x5f\xbd\x47\xff\x06\x77\xd6\xc9\xcf\xfe\x2e\x06\xd4\x3e\x14\x09\x1f\x7d\xa3\xaa\xf9\xf1\xb7\x59\x5a\x77\xe1\x5c\xd7\xf0\xda\x66\xea\x7e\x3f\xe2\xc3\x5c\x01\xcb\xfc\xba\x83\xd4\x90\xa2\x55\x44\xb2\x74\x34\xfb\x18\x80\x84\x55\xc2\xe6\xe5\x8a\x1b\x4d\xc0\x0b\x83\x55\xd4\x89\xbf\xc2\x21\x1a\x01\xbc\xf2\xf7\xba\xdc\xa9\x79\x6e\xf7\x97\xdd\xf7\xfc\xfe\xfa\xcb\x6f\x23\x02\x08\x40\x76\x19\xf2\x99\x2e\x6d\x46\xf8\xea\xe6\xa4\x9f\x9e\x07\xbd\x3e\x05\xeb\x1c\x04\x51\x10\x0c\xb4\x1b\x9a\x63\xa8\xaf\x03\xcc\x24\x56\x0c\x0e\x9f\x66\xd3\x63\xba\xef\x84\xd5\xd0\x1a\xcf\x69\x47\x1c\x8e\xdc\x2e\x97\x32\x84\x95\x08\x45\x62\x83\xa7\xd3\x04\x0b\x56\x09\x7a\x0a\x19\x05\xcc\x0a\x87\x37\x14\xa1\xc9\xfa\x6c\x96\x1e\xb6\x2f\x03\xb4\x05\x60\x65\x18\xc5\x30\xe0\x7a\x27\x01\xc5\x2e\xc6\xd8\xda\xe8\x3d\x2f\xfd\xf8\x3b\xbe\xde\xa0\x67\x1a\x0e\x80\x63\x88\xd9\x03\xd0\x41\xd0\xf6\x1e\x43\xa5\x47\x91\xa7\xf3\xc6\x1d\x03\x40\x44\x5d\x16\x83\x9d\xa3\xe1\x20\x38\xe6\x68\xd6\x43\x15\xfb\xca\xec\x84\x2b\x7a\x1b\xc6\x1a\x68\x97\x61\x85\x72\x73\x27\xa2\xbb\x64\x4b\xe2\xae\x2e\x9b\x61\x99\xcf\x4e\x82\x1e\x27\xf5\x99\x51\xa0\x06\x8c\x50\x10\x9c\x34\x17\x14\xe3\xe6\xd2\xec\x1a\xea\x72\xcf\x32\x68\x1c\x7f\x1f\xb6\xea\xea\xee\x95\xf2\xc5\x1e\x01\xe9\x51\x8d\x5d\x5a\xee\xa8\xb0\x2c\x9b\x99\x5d\x25\x1b\xa6\x78\xe9\x2a\xe1\xaf\x7e\x99\xca\xef\x55\xb0\x21\x35\x83\x52\x3f\x4b\x5b\x34\xd4\x5d\xea\x7e\xd6\x1c\xff\xce\x86\x97\x5a\xd3\x2d\xf4\xde\xb3\xcd\xba\x05\xe1\x0e\xd6\x6a\x41\x7a\x9f\xd2\xfb\xad\x2d\x2c\x29\xda\x5e\xab\x01\x0c\xc2\x67\x2e\x89\x88\x8b\xd4\xd6\x14\x58\x1a\x72\x05\xc1\x17\x64\x34\x1e\xe1\xce\x32\xf5\xa1\xfc\x13\xb8\x4c\x3a\x34\x84\xca\x37\x80\xcb\xa5\x33\x41\x18\xfc\xa9\xac\x1b\x2e\x5b\xc0\x13\x4a\x52\x69\x75\xa9\x44\x3a\x87\x4b\x73\x72\x2e\x95\x67\xe0\x32\x6c\xab\x24\xf4\x44\xa4\x18\xd1\x9a\x8a\xe5\xa8\x8e\xf1\xee\x91\x72\x88\xc9\x2a\x32\xf7\x48\x06\xc3\xa3\x11\xa0\x33\xaa\x6e\xae\x91\x36\x80\xb7\x97\xd3\xad\x27\x95\x01\x66\xad\xd5\x50\x47\x29\xeb\x37\x52\xa9\x81\xdf\x4c\x55\x64\xae\x8e\x88\x44\x6a\xd1\xa5\x60\x29\x2b\x6e\x86\xc3\x61\x20\x32\xff\xfe\x96\x98\x1d\x96\x80\xa6\x43\x01\x70\x50\x80\x0f\x23\x56\x95\xff\x62\xa1\x2b\xcf\x8c\xf9\xf1\xf8\x30\xeb\xbb\x53\xbc\x54\x4f\xf9\xce\x7e\x50\x2f\x92\x3c\x2f\xbf\xbc\xfa\xdb\x3a\xc9\xed\xe4\xea\xbb\x2c\xe2\x64\x84\x4e\xa4\x05\xe8\xc8\x7f\x85\x3d\x21\x3f\x73\x33\xf5\xf6\x10\x3b\x53\x8d\xfc\x0c\x28\xee\x5d\xc2\xd6\xb4\xed\xef\xf0\x98\xbc\xe0\x28\x2c\x58\xa9\x3f\x50\x49\xd2\xbc\x8d\xec\xd5\x04\xac\x85\x4a\xfd\x2e\x1e\x2a\x43\x7c\x13\x62\xe6\xc6\x23\xd3\x67\x99\xe2\xb8\x20\x48\xec\x58\xab\x68\xfc\x98\xd6\x7e\x97\xe1\x94\x4b\x6d\x60\xd0\x87\x7e\xd3\x93\x69\x05\xca\x79\x2f\x35\x73\x7a\x7d\xbc\x5d\xa5\x76\x5e\x2f\x8c\xa2\x8a\x41\x81\x90\xa8\xec\x25\xb5\x91\x53\x3c\x30\x52\x71\x64\xaa\x75\x4f\x76\xde\xf4\xf8\x18\x4f\x2b\xfa\x09\xfb\xbb\xfa\xb0\x5e\xa5\x80\xa9\xbe\xae\xd0\x5b\x06\x9b\xa3\xe4\xee\x69\x46\x71\xcc\xaf\xd3\x1e\x7e\x8d\xa1\x6f\x74\xdf\x21\x65\xac\x01\x9c\x22\x7a\x18\x70\x6a\x69\x4e\x25\x21\x63\x05\x33\x51\xd9\x87\xee\xcd\xcc\x5f\xc8\xf6\xc0\xea\xac\x31\x6f\x4f\x24\xad\x57\xc2\xb4\x58\x2f\xd3\x8a\xa2\xfd\x1f\x8d\xc3\x2f\x55\xd6\xf0\xf3\x08\xad\x7a\xe7\xd9\xcd\x5a\xbc\x1b\x6d\xd0\x88\x80\x72\x33\x5e\x5d\x51\xa3\x57\x57\x30\xad\x0d\x5b\x3f\x1b\xa4\xad\x5a\x9a\xc6\x8d\xa8\x3b\x72\xb3\xd7\x89\xf0\xce\x94\xdf\xb8\x1a\xea\x91\xc4\xe6\x0f\x8a\xb7\x57\x0d\xcd\xd1\x20\x1a\x0c\x68\x02\x18\xe4\xb6\x82\x41\x55\x43\x39\xf2\x18\x11\x60\x57\x38\xe4\x0a\x8d\x7d\x42\x0c\xc8\xe1\xa6\x8f\x40\xbf\xbd\x4a\x07\xe2\x3d\x3e\x6e\xac\xac\x69\x40\x79\x54\x54\x06\x95\xc2\x74\xb3\xe9\x0f\xac\xe4\xae\x22\xaf\x8d\x4c\x0d\x05\x63\x98\x54\x93\x81\x48\xdf\xdc\x00\xf1\x9a\x42\xf5\x62\x52\xc7\xd3\x78\x2d\x52\x09\x87\x50\x8b\xb3\xdc\xd7\x3b\x43\x3c\x63\x66\x70\x3c\x93\xfc\x25\x80\x53\xcd\x10\xa7\x96\xa0\x96\x51\xab\x85\x47\xe6\x84\xed\xc9\x49\xd2\xd0\x0a\x34\xbe\x16\xe9\x95\xa3\xb5\xc8\x69\xc1\x9b\x38\x35\x86\xf1\x4e\x4e\xfc\xed\xbc\x9f\x71\x4e\x71\xbe\x75\xa6\x56\xee\xf3\xd1\xa4\x89\xa7\x61\x1a\x97\xe8\x55\x8f\x13\x42\xc9\x51\xad\x42\x42\x63\x46\x30\x2b\xe9\xd6\x7a\x7b\x82\xc6\x46\x64\x8f\x17\x19\x42\x60\x89\xfb\xfe\x21\x19\x3b\x33\xc0\xf0\xa8\x0a\xac\x59\x42\x34\xd0\x89\x80\x85\x00\xf7\x0b\x67\xd7\xf9\x73\x7a\xfd\x81\xd0\x3c\x10\x0d\x98\xd2\x29\x38\x51\xb7\xeb\x94\x13\xf4\xe1\x85\x7e\x12\x3c\xf8\x52\x07\xea\x4b\xb8\x17\x91\xfd\xf3\x84\x7d\x6f\x28\x5d\xa4\xa5\x95\xd3\xdf\x50\x28\x83\x2d\x1f\x19\x31\x30\xad\xef\xc4\x7d\xe7\x49\x8d\xf5\x2f\x1f\xde\xfe\x82\xe1\x13\x6a\x38\xd9\x43\xb8\x14\x12\x3c\xfb\xd4\x58\xc1\x56\xff\x18\xb0\xb2\x06\x5c\x5d\xa7\x1a\xc0\x33\x00\xd9\x06\xd3\xb6\xa7\xe1\x05\x89\x5c\x44\xbc\x59\x3e\xfe\xf6\xad\x22\x07\x41\x56\x80\xd4\x1b\x22\xd3\xe2\x26\x9b\xdf\xf6\xd9\x6d\x0c\x4e\x50\xfa\xb7\x75\x0a\xe4\x0f\x1b\x7b\x5d\xe2\x61\xe8\xd7\xe6\xfd\x85\xeb\xbc\x96\xa1\xa2\xeb\xe8\x21\x21\xeb\x5d\x16\x55\x1d\xac\x61\x49\x76\x0f\x9f\xfb\x77\x14\xc5\xb3\x09\x35\xbf\x0b\x3f\x90\x3a\x8c\x30\xc0\x3b\x3a\xad\x39\x79\x98\x88\xfe\x93\x01\xe1\xff\x99\x24\x57\x28\xb1\x4a\xe3\xa0\x04\x06\xf3\x44\x16\x90\x09\x75\xf0\x39\x10\x88\xcd\x08\x9d\x08\xc7\x9d\x46\x62\xe5\x5c\x52\x16\x28\x44\x37\x8a\xe6\x4f\xd1\xad\xa2\x19\xe2\x68\xb4\x6b\x70\x19\x0c\xb0\xb3\x7f\x06\x9e\x36\xf2\x56\x80\x3e\xb9\xf3\x13\xa8\xc2\x5c\x0d\x91\x09\x72\x7e\x81\xd5\x77\x62\x33\xcc\x71\x63\x70\xfe\x76\x48\x47\x38\x8c\x69\xf7\x4b\xbd\x14\xc7\xc7\xf0\x8c\xf7\x12\x2e\xcb\xe9\x38\xe2\x37\xa9\xf1\x86\x16\x6c\x6c\x2d\x16\x3c\x9b\x9f\x9c\x18\x9f\x9c\x18\x9f\xa4\xcf\x1a\x7c\xdf\x3c\x4b\xe1\xc7\x48\xcf\xa2\xd6\x87\x60\xb1\x61\x04\x65\x4a\xfe\x89\x07\xcf\x96\xcb\x35\xa1\x71\xc9\x7c\x2b\x01\x80\x1b\xff\x45\x73\xf5\x6e\x00\x18\xc5\xbd\x63\xe8\xc1\x37\x09\x66\xe8\x99\xc1\x13\x4a\x81\xe0\xf1\x33\x3c\xbe\x4f\xa7\x65\x35\x13\x60\xc5\x76\x12\x1a\xb2\xe8\x37\x01\x17\x42\x56\xb8\x8c\xd7\x66\xa6\x46\x7f\x7e\x23\x3b\x3f\xc8\xca\xca\xec\xfa\xb1\xec\xcf\x25\x9d\x4c\x61\x9e\x3f\x58\xba\x25\xa3\x92\x46\x09\x32\x3e\x79\x67\x55\xa4\xdb\x39\x42\xee\x07\x69\x7b\xb0\x09\x91\xc5\x77\x8e\x74\x2e\x98\x43\x8b\xa0\x5f\xc4\x0b\xb8\x1a\xd1\x42\x16\x95\xed\x80\x1f\x88\x31\x17\xb1\xd8\x28\x19\x53\x7f\x01\xcd\x09\xf1\x44\xe4\x9e\x5c\xfc\x9c\x1d\xbe\xf8\xf3\x22\x14\xdc\xe2\x65\x38\xb3\x98\x4f\x9d\x1d\x83\x44\xc0\xe8\xa8\x35\xac\x01\x49\xe0\x8d\xe3\xe9\x4f\xf3\xf1\xed\x2e\x51\x2d\x2f\x7a\xbb\xc4\x93\xb3\x65\x0c\xde\x11\x88\x30\x06\xde\x77\x08\x05\x08\xbd\x1b\xcf\xa8\xac\x61\x3d\xcf\x73\x67\x79\x17\x64\x11\xe0\x4d\x71\x82\xd4\x84\x3b\xca\xea\x77\x1a\xa5\x7f\xf5\xa4\x2c\xc2\xb3\x7a\x38\xca\xc2\x33\xca\x0a\xed\x37\xec\x51\x16\x61\xe6\x19\xa5\x91\x8a\x03\x48\xaa\x19\xda\x88\x7e\xed\x1e\x67\x4c\xe3\x54\xe9\x11\x44\xeb\xd0\x9b\xc7\x08\xae\xec\x0b\xe4\xc7\xf2\x19\x14\x89\x1b\x50\xe2\x9b\xa9\x94\x42\xb4\xe6\xd9\xc4\x39\x87\xa9\xf0\xf5\x43\x09\xd8\x54\xcb\x21\x4e\xba\x66\x6b\x13\x0b\x7a\x04\x9e\x68\x06\xfe\x8e\x49\x78\xe1\x3d\x11\x66\x63\x2c\xfa\xb8\x54\x29\xa1\x9d\x46\x50\x80\xe1\x31\x6c\x5c\x48\xf3\x97\xb6\x4c\x44\x8d\x6f\xb0\xef\xf2\x93\x18\x03\xf6\xc0\xde\xdc\xee\x96\xc3\xd4\x0b\x93\x12\x7f\x08\x21\x9b\xb5\xb0\x78\xd5\xd0\xce\xb1\x9c\x26\xe5\x2b\x4e\x44\x78\x84\xa5\x09\x02\xb2\xb2\xf1\x56\x3b\xa1\x78\x24\x44\x97\x60\x9d\x7d\x47\x79\xe9\xdb\xd9\x66\x1b\x52\x41\x14\x69\xad\x75\x27\x46\xac\x5b\x8b\x8f\x07\x0a\x21\x02\xef\x10\xa1\x1f\x54\xd7\x08\x87\x53\x13\x52\x2c\x61\x4e\xe4\x41\xa0\x42\x34\x64\xf5\x45\x26\x46\xc8\xff\xf6\x45\xb7\x30\x18\x71\x51\x75\xe3\x1f\x5f\x43\xf1\xe2\x22\x60\x3c\x1e\x5c\xf6\x7d\xb0\x66\xdc\x0f\x7b\xac\x01\x8f\x4b\xc6\x89\xb1\xc6\x27\x0b\xd5\x38\xbd\xf3\x45\x19\x80\x14\x7b\x79\xf6\x89\xd1\x50\xc3\x15\xdb\x27\xd8\xae\x47\x5b\x01\xa7\x4b\x01\xfe\xfd\xfd\x8c\x3e\x6c\x9f\xc0\x8e\x0f\xc5\x21\xe4\xee\x2c\x9d\x7a\x1d\x4a\xb9\x60\x54\x5b\x6a\x93\xe5\xb7\xc4\x3a\x50\x24\x4b\xd4\x99\x28\xe1\xf1\x2e\x23\x73\x83\xfe\x95\xb3\x21\xb2\x71\x7d\x8e\xee\xbb\x44\x92\x98\xa1\xf9\xba\xed\x2a\xbb\x9c\xb6\x90\x5d\x1d\x9f\xfd\x10\x52\xa6\xfb\x75\x7c\x3a\x06\x72\x0b\x99\x9e\x1c\x89\x1a\x74\x9b\x34\xab\x4f\xa6\x18\x67\xc7\xe4\x37\xa6\x03\x99\x01\x3c\x3b\x94\x18\x2a\xf9\x20\x38\xc1\x8a\x38\x9c\x0e\x70\xd4\xc8\xcc\x32\x25\x5e\x0f\xd7\x45\xbd\xc8\xe6\x08\x22\xa1\xf4\x7f\x7e\x96\x60\x10\x68\x91\x66\xb1\x6b\xbc\xb1\xc3\xab\xd4\x7c\x6c\x00\x72\xcd\xa1\xf1\x82\x42\x47\x34\x7d\x0b\x78\x71\x91\xf1\x1b\xe5\x74\x64\x7e\xb7\xc6\x21\x8a\xe1\x9c\x62\xbe\xad\xf5\xc9\x89\xff\x73\xe5\x97\xe4\xef\xf6\xf4\xd4\xff\x99\x0b\x9e\x95\x06\xcf\x6a\xab\xb5\x73\xdb\x9d\xa6\x0b\xfe\x76\xd9\x24\x7b\x84\x65\x6c\x64\x1e\x4b\xc3\xf3\x90\x5d\xb0\xa4\x97\xad\x62\x64\x44\x78\xf5\x60\xa0\x84\x8f\x64\x8f\x3e\xe1\x3f\xec\xed\xca\xfe\xa0\x71\xc0\xe3\x46\x6d\x8e\x64\x72\x8b\x13\xdd\x24\xb3\x5e\xdf\x03\xdb\x13\xcf\x7d\x97\x01\xa0\xe2\xc5\x16\xf2\x12\x07\x3a\xe3\x6c\x74\xde\xa3\xe2\x30\x17\x89\xc5\x5c\x08\x8d\xa1\xe2\x1c\x84\xa2\x50\xf3\x18\xae\x35\xb1\x56\x1d\xba\xb1\x3d\x54\x1b\xdb\x18\x96\x52\xf0\x25\x0b\x78\x12\x17\xca\x0c\x83\x3d\x0b\xbe\x24\x9b\x31\x17\x22\xd4\x36\xf4\x8c\xcb\xc9\x4f\x4d\x29\x78\x14\xa1\xb8\x09\x30\x88\x9d\x64\x5c\x88\x4d\xa7\x27\x72\x26\xc6\xb4\x7f\xc8\xf3\x1c\x7c\x6c\xa7\x2e\xcf\x91\x5b\xec\x89\x29\xbd\x70\x2a\xae\x28\xc4\xa3\xc8\xc7\x44\x04\x4f\x31\x6b\x51\x4c\x95\x11\x3f\x9f\x66\x46\xa2\x2a\xca\x37\x80\x4a\x3e\x3b\x3f\x0d\x8a\x82\xac\x93\x33\xf7\xe0\x14\x15\xed\xac\x44\x4b\x3e\x03\x06\x8f\x8f\x05\x07\x8e\x3f\xac\xe8\x5d\xc4\x81\x2b\x4d\x9d\xe0\xf8\xdb\x3d\x29\x25\x61\x6b\x16\x64\x8b\x25\xaf\x3c\x2f\x1b\x80\x92\xbb\xbb\xfe\x51\x71\x7f\x5f\x1c\x1f\x93\x55\x81\x54\xad\x31\x25\xe7\x73\x0b\x69\x24\x11\x87\x66\xca\xc7\xc7\x7a\xa9\x30\x88\xab\x19\x3c\x42\xf8\x5a\xa0\x8a\x05\x3d\xa3\x5b\x77\xf2\x9c\x50\x1a\xea\x5f\x5a\x23\x4f\x28\xaf\x18\xe5\x9a\x1e\x9c\x27\x3e\x72\xc0\xe9\xb6\xe8\xea\x16\xa6\x86\x24\x5c\x74\x50\xfd\xf6\x38\x35\x40\x59\xbb\x0a\xb8\x60\x0b\x8d\x33\xf7\x33\xbd\xde\xf9\x20\x56\xd9\xc1\xf4\xce\x19\x19\x0b\x3f\xbc\x0e\xea\x64\x6e\x10\x19\x48\x95\x2c\x36\x1a\x5d\xb7\xa5\x7d\x73\xdb\x2e\xe3\xf3\xbe\x04\x46\xa7\x2f\xa4\xa3\xc9\x72\x8c\x81\x2c\xbb\xe2\x7d\x08\x93\x5d\x9e\x1d\x16\x61\x22\x84\xa5\xd0\x67\x45\x91\x57\x30\xb3\x03\x5d\xba\x1c\x87\x05\x5d\x90\x82\xf1\x93\xd5\xd7\xde\xcb\x0a\xa5\xc3\x1f\x92\xa2\xee\xbd\x29\x8b\x12\x50\x84\xcf\xc5\x30\x7e\xf2\x07\xd5\x94\x29\xbf\x93\xc2\xe0\x7c\x68\x6c\x46\x7f\x21\xef\x81\x85\xb6\xd8\x95\x65\x3a\x32\x02\xde\xd5\xe7\x40\xbb\x34\x80\xe0\xa7\x43\x74\xa0\x55\x0d\x34\xe1\x2c\x54\xfd\x85\xd6\x48\x06\xa8\x35\xc5\x00\x8b\x86\xb4\x4f\x6d\x61\x42\xd7\x49\x12\xd6\xa1\x2b\xaf\xf2\x50\x5f\xd2\xf1\x4f\x18\x8e\xb8\x81\x9e\x76\x04\x49\xd7\xd5\x17\xf1\xca\x50\x5e\xc3\xe5\x60\x1a\xf9\xf1\x0c\x3e\xef\x12\x4c\xc1\x96\x85\x19\x46\x37\xd4\x79\x17\xab\x70\x9c\x3e\x6c\x4b\x93\xcc\x70\x3a\x4e\x92\xb1\xd6\x35\xa0\x83\x4b\x69\xc3\x56\xe7\x02\xf0\xdb\xb6\x12\xeb\xab\x1a\xb6\x4e\xf9\xcc\xb7\x5f\xc9\xb6\xfd\xb2\xce\x2d\x70\x7e\xa1\x33\x28\x2b\xba\x12\x11\x9a\xee\x07\x3b\xec\x38\x31\xce\x90\xff\x43\x97\x5c\x2b\xf5\xf9\x2f\xb7\x1e\xf6\xd6\x99\xd6\x5e\x65\x06\xa8\xc0\x49\xfe\x21\x74\x20\xc5\xd2\x3c\x3b\x47\xf8\xc9\x2e\x27\x00\x0f\x6f\xd1\x9b\xee\x4d\x22\xed\x1d\xfb\xa5\x3b\x7c\x84\xe1\x92\x25\xe9\x9e\x5c\xd3\x3d\xab\xc3\x69\x93\xc4\x85\x38\x32\xa5\x52\x80\xf9\x7c\x36\xf3\x40\xe5\xba\x93\x7e\x81\xab\x73\x95\x16\x0e\xb6\x9f\x02\x38\x0a\xb1\x55\x13\xe6\x7e\xb1\x03\xd1\x9d\x69\xeb\x1a\x99\xa2\x51\x32\x6a\x7f\xb6\x35\xe9\x6b\xd0\xbc\xe9\x14\xa1\x92\xb6\x79\xed\xa9\x86\x77\x9a\xab\xcb\x5b\x01\x05\xd4\x45\xf2\x08\x47\x7f\x6f\x88\x9b\xce\x4b\x18\x06\xbe\xe5\x12\x9e\x1e\xc2\xc2\xb8\x6e\x36\x9d\xf7\xdc\x8e\x38\xc4\x7e\xf6\xdb\x39\x19\x07\xc4\xd8\x57\x9b\xb0\xfe\x96\x93\x61\xf8\x75\x6b\x22\x1e\xbd\x84\x51\xa5\x2e\xec\x65\x22\x09\xf1\x1b\x3c\x21\xc8\xad\xd4\x70\x20\xbe\x01\xf6\x11\x75\x49\x73\x1c\x6b\x9b\xd6\xf1\x5a\xaa\x91\xd8\x61\x36\x2c\x3b\x84\x99\x6b\xd4\x38\x52\xe8\x6c\x8b\xd1\x95\xdf\xe3\xc8\x83\xf0\x68\x4d\x8e\xce\x9e\x4f\xf7\xde\xed\xe9\x16\xf7\xdc\x2d\xfb\xb6\xcb\xd2\xd8\xb7\x6f\x37\x42\x48\x70\xa3\x02\xef\x9e\xf7\x97\xf1\xcd\xc5\x8d\xe2\xdc\x2f\x5b\x97\x3c\xa9\x0a\x97\xf1\x92\x67\xad\xad\x18\x07\x42\x20\xcd\x41\x54\xa1\x4d\xb3\x95\x78\xe9\xa5\x12\x96\x4c\x25\x58\x70\x53\xbb\x70\xb3\xb6\x98\xce\xa9\xc3\x74\xba\x9c\x24\x5b\x95\x7e\x93\xde\xcb\xef\xfa\x3a\xdb\x8a\xd0\x3f\xc7\xb5\x86\x5d\x83\xf1\x6c\x7b\x6d\x92\x38\x0a\x35\x63\xa4\x9d\x0d\x6f\x50\xa6\x74\x1b\x27\x87\x82\x72\xbe\x9d\x73\x74\x5e\xce\x38\x39\x80\xcc\x13\xba\x5d\x7b\xb6\x95\x3d\x15\x7a\x2d\x16\x2d\xfa\x2f\x8b\x95\xa1\x60\x53\x81\x61\xf7\xd2\xc2\x39\x75\x16\xde\x2c\x49\x92\xfa\xf0\x30\xb0\xca\x4a\x43\xe7\x13\x1f\x5f\x9e\xe3\x8a\x47\x66\xc9\x44\x2c\x7e\xdf\x97\xf8\x93\x36\x29\xbd\xbf\x9f\x12\x4f\x0d\x3f\xd8\xc2\xef\x86\x2f\xac\xa5\x73\xa2\x97\x7e\x26\x2a\x85\x31\x2c\x95\x6f\x9b\xb8\x4f\xe4\x55\xb2\x54\xc6\x8b\x68\x7b\xd3\x47\x59\x71\xfb\x1c\x51\x20\x7a\xf3\x28\xe9\xf1\xa4\x03\x17\x25\x2d\x07\x1d\xb7\x66\x63\x8d\x83\x47\xa5\xbc\x52\xbe\xa5\xef\xc6\xdf\x77\xc7\xdd\x67\x77\xdf\x5f\x0b\x45\x48\xff\xc6\xcc\xe0\x19\xca\x61\xd0\x9e\xf8\x5a\x57\xa0\xd6\xe2\xc4\x8d\xd9\xd8\x4b\x8e\x3d\x4f\x95\x54\x24\x1d\x88\x4d\x28\x6c\x9d\x7e\x7b\x4b\xec\xf7\xb8\x41\x19\xc9\x54\x5a\x63\x32\x81\xbb\x23\xce\xc6\x64\xed\x15\x0d\x28\xbd\x8b\xf4\x88\x34\x46\x4d\x5a\x93\x23\x6b\x97\x04\xf0\x50\xdc\xf5\x36\x04\x9d\xc3\xf8\x1a\x91\x9e\x22\x35\x46\x18\x1e\x8d\x07\x11\x1f\x87\xcd\x16\x5d\x06\x0f\x76\xcd\xd2\x94\x26\xbc\x13\x9a\x8a\x48\x0e\x09\x2f\xa4\xe3\xe3\x23\x13\x68\x14\xb8\x30\x68\xc8\xdc\x18\x0e\x9a\xf7\xac\x98\x27\xb7\x19\x0a\x78\x63\xf3\x68\xb0\x60\xc9\x00\x19\x89\x26\xdb\xcd\x29\x1f\x13\x8f\xe0\x40\x0d\xdf\xd0\xaa\x78\xab\x89\x69\xed\xe4\x4b\x6e\xdb\x36\xba\x5a\x68\x26\x1a\x21\xbb\x4f\xc9\x53\x67\x48\x7b\x92\x4d\xdb\x84\x9d\xbf\xd0\xd4\x63\x32\x20\x75\x9e\xb0\x92\x99\x2c\x0c\x0b\xe4\x07\xda\xfc\xf9\x04\x7f\xa4\x22\xd8\x57\x47\x1d\xd8\x16\x7c\x3b\x92\x50\x2e\x58\x5d\x4a\x56\x74\x7c\xbc\xf0\x05\x3d\x98\x58\x1a\x00\x83\x41\x72\x15\x00\x84\xee\x34\x19\x72\xfb\xbb\x24\xbf\x70\x3c\xc2\xbb\xc2\x5e\x7b\x6d\x8b\x0f\x93\xca\x3c\x39\xc0\x93\xe6\x1b\x58\x3a\x47\xea\xdd\x99\x7e\xd6\xa5\x44\x6c\xf6\xad\x6d\x43\x63\xd2\x06\xdf\xc0\xd5\xd5\xe4\x23\xea\x62\x60\x9d\xd9\xb6\x32\x0f\x59\x04\xd0\x50\x61\x72\x05\xc3\x6a\x6b\x14\x56\x03\x1c\xe5\x54\xe8\x54\xf1\xd8\xe5\x62\x80\x69\x2b\x63\x73\x8b\x8b\xd1\x69\x69\x9b\xdf\xc2\x0a\x89\xb4\xb9\xdd\xbc\x5f\xea\x57\x62\x18\x36\x10\x8d\x97\xe3\x6b\x69\xb2\xbd\x62\x4e\x35\x7d\xa5\xb2\xe5\x65\x68\xfc\x6c\xe4\x4d\x6b\xb4\x1a\xa0\xb4\xa0\x93\xc7\x25\x54\xa9\x64\x24\xb5\xab\xbe\x88\xde\xf1\xed\x8c\xe1\xce\x63\xb5\xcf\x39\xda\xdb\x3e\x5f\x1e\x89\x49\x31\xfc\xf4\xe9\xa7\x97\x6d\xb3\xcd\xe0\xab\xf8\xdf\x29\xfd\xf3\x08\xff\xb9\x95\x3f\xe5\xff\x02\x65\xfc\xf0\xe0\xe2\xeb\xed\xe5\x83\x1b\x8f\x4f\xca\xf8\xc9\x1f\xde\x24\xcd\x62\x58\x25\xc5\xac\x5c\x02\xd9\x30\xc2\x60\xb0\x5f\x01\xbf\x36\xe7\x69\xf4\xf0\x38\xbd\xff\x41\xdb\xcd\x34\xe5\x07\xc2\x69\xfd\xf1\x13\xf2\x97\x28\x74\x44\xa8\xd8\x26\x52\x30\xef\x8f\xd0\xd4\x89\xbc\x2f\x15\x10\xd3\x33\x0c\xef\xd6\x27\xf3\xd9\x3f\x95\xeb\xaa\x86\xa3\x0b\x5c\xf6\x28\xc0\xbc\x2f\xce\xfb\x37\x59\x01\xe8\x4d\xd7\x90\x83\x48\x4f\xd0\x60\xb2\xc0\xbe\x4d\xe9\x5c\xcb\xf6\x99\x97\xd2\x43\xbd\x3e\xbc\x3c\x1f\x45\xe6\x4f\xed\x5c\xfc\x25\x6b\x16\x6f\x60\x13\x69\x67\x0d\x9d\x89\xb6\xa4\x2e\xe3\x11\xe2\x2c\xba\x14\x26\xc9\xb3\x72\x52\x4a\xab\x71\xc0\x5d\xa4\x4d\x29\x11\x5b\xf5\x9f\x9c\xf4\x6b\x12\x62\x9c\xf3\x1f\x71\x8f\x9f\x8c\xa3\xd1\x60\xf0\x87\x02\xef\xb5\xf5\x89\x11\x23\x98\xde\xfe\xa1\x78\x9a\x0e\x32\x69\xf7\x51\x02\x21\x8f\x1a\xb3\xe0\x32\xbc\x50\x35\x2f\xf9\x96\x12\x99\xb5\x75\x03\x56\x62\xed\x20\x00\x74\x07\x2c\xd0\x1c\x06\xbb\x40\xa3\xee\xa9\x91\xfc\xa5\x16\x3a\xa8\xf5\x09\xe5\xdf\x96\x3d\x3f\x8b\xd1\xe2\x74\xc5\x14\x79\x8e\x73\x18\xe9\x40\xe0\x33\x68\x08\xcd\x14\x85\xa5\xfc\xe7\x67\xb3\xc9\x4c\xce\x7b\x09\x08\x68\x76\x39\x59\x90\x0d\xdc\xd1\x38\x5c\x9f\xc4\x18\x8f\xf3\x24\x5e\xaa\xb6\xc3\xf9\xc9\x49\xb8\x86\x1e\xce\xfb\x48\x78\xcd\xcf\x8d\x7e\x66\x50\xf0\xf9\x74\x7c\xde\xcf\xe3\xe5\x09\x0a\xec\x61\xf1\xf4\x6a\x0d\xf0\xe3\x18\xc8\xae\x95\x64\x15\x06\x51\x5f\x3d\xe3\x20\x71\x92\xc8\x60\x22\x2b\xad\xdb\x3a\x91\x8d\x9d\xc4\x05\x7c\x81\xbf\x43\xd5\xe7\x60\xe3\x5b\xe3\x15\x7a\x7b\x0c\x36\x13\xbe\xb4\x66\xe5\x94\xe0\xc3\x75\x87\x9d\x26\xc5\xe7\xa4\xa6\x9b\x8c\x94\x67\x2f\xd8\xe9\xa4\x1f\x9c\xcd\xe8\xb0\x1a\xea\x07\x27\x5f\xbd\xb4\x2e\x1b\xce\xe1\x93\x38\x0d\x4b\xd8\xbb\xa4\x5e\x57\x29\x46\x44\x84\x33\xc3\xc1\xe4\x11\xac\x39\x4a\xfe\xb5\xd4\x69\x18\x47\x9f\xd5\x10\x5d\x63\x43\x37\x6e\x8a\xb8\x8f\x8e\xde\xc3\xcf\x59\x9d\x5d\x67\x00\x15\xb7\x71\xb0\xc8\x80\xd2\x27\x3d\x37\xbf\xe3\xb8\xf5\xc1\x78\x34\x5a\x7d\x0d\x42\xd5\xde\x75\x39\xbb\x1d\x26\xab\x55\x5a\xcc\x28\x02\x3e\x8c\x4a\xe5\x6c\xb2\x82\xe1\x8b\x66\x80\xed\xa8\xe6\x79\xf9\x25\x0e\x78\xc8\x8c\xbf\x8a\x1d\x03\x2c\x5a\x83\xf8\x27\x1c\x99\xd9\x6f\x31\x98\x48\xe3\x3e\xb3\x5f\x2d\xe7\x4c\xd0\xaf\xe7\x17\xb6\xee\x42\xee\x47\x0e\x37\x4c\x4f\x2b\xf4\xd9\xd1\x4e\x51\xf0\x63\x13\x62\x4e\xf7\xc9\xff\x06\x4c\x8a\x20\x17\xcd\xb1\x05\x00" - -func bundle_js_gz_bytes() ([]byte, error) { - return bindata_read( - _bundle_js_gz, - "bundle.js.gz", - ) -} - -func bundle_js_gz() (*asset, error) { - bytes, err := bundle_js_gz_bytes() - if err != nil { - return nil, err - } - - info := bindata_file_info{name: "bundle.js.gz", size: 104914, mode: os.FileMode(438), modTime: time.Unix(1432348676, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _font_fontello_eot_gz = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x0b\xe5\x57\x6b\x6c\x5b\xd7\x7d\x3f\xe7\x5e\xf2\x92\xa2\x1e\xa4\x2c\x89\x92\x45\x99\x3e\xd4\xb5\x28\x59\xbc\xa4\x64\xea\x69\x59\x66\x14\x52\x0f\xc7\xb2\x1d\x5a\x56\x3c\xd2\x49\x13\x52\x14\xf5\x70\xf4\xe0\xf4\x30\x94\x07\x82\x60\x4d\x87\x4c\xc8\x32\x23\x28\x8c\x61\xcd\x80\xae\x70\x8a\xa2\x9f\x0e\x9d\x74\x49\x87\x00\x29\x86\xb5\x68\x87\x06\xd8\xb0\xa0\xd8\x87\x3d\xfa\xa1\x1f\x54\xac\x43\x3f\x6c\x2b\x30\x60\x91\xf6\xfb\xdf\x7b\x25\xcb\xb2\xbc\x01\xc5\xbe\x8d\x14\xcf\xff\x71\x7e\xf7\xfc\xff\xe7\xff\x38\xf7\xe8\xbf\x9a\x18\x9b\xc6\x8f\x33\x85\xd1\x47\x61\x4e\xd5\x64\xa0\xb9\xcb\x89\x5e\x49\xb3\x23\x1f\x6e\xd3\x9e\x6f\x2c\x7c\x7e\x74\x8e\x31\x1f\x9b\x63\xab\x6c\x85\x6d\xb0\x22\x5b\xc2\x77\x15\xba\x1a\x36\x05\x69\x9e\x6d\x42\xce\xb3\x35\x68\xfc\xec\x26\x34\x6b\x6c\x9d\x2d\x9a\x68\xc1\xce\xb1\x18\xeb\x7e\xc2\xf3\xb6\xd1\x1a\xf6\x26\x53\x59\xee\xd9\x1b\x5d\xf1\x44\xc7\xa5\x7f\x83\xe6\x57\xf8\xdd\x2c\x2c\xe7\x4b\x7f\x73\xf2\xe4\xc7\x00\x8d\xe2\x77\xb9\x70\x67\x43\x58\x0f\x55\xbd\x80\xc1\x33\x57\x9a\x5f\x7e\xfb\xee\xdd\x2c\xe4\x05\xc6\x2a\x4b\xf3\xf9\xf5\x92\x69\x88\x55\x4d\x83\xba\xe7\x97\x5e\x99\xfb\x4d\xfd\xfb\x03\xd8\xfd\x5d\xc6\x9c\x3f\x5e\x28\xe6\x67\xb5\xc1\xa9\x5a\x4c\x65\x30\xdf\xbf\x00\x85\xeb\x9f\xd5\x6f\x41\xc6\x3c\x3b\xb3\xb0\xbc\xb1\x15\xfa\x3a\xad\xef\xfe\x08\x43\xc7\xd2\x6a\x21\x5f\xd1\xe4\x32\x20\xff\x03\x6d\x6d\x39\xbf\x55\x62\xdf\xae\xfc\x17\xc8\xff\x0e\x59\xac\xe4\x97\x8b\x3f\xfd\xd3\xc0\x29\xc6\x2a\xea\x61\xe3\xf3\xd2\xea\xfa\xc6\x77\x7f\x3e\x79\x1e\xbe\xfc\x02\xf3\xab\xa5\xb5\x62\xe9\x1f\x5f\x56\xbf\xc6\x58\xe3\xdf\x43\x7e\x8d\x71\xf5\x05\x7e\x97\x39\x99\x5b\x79\x55\xf9\x14\x9a\x77\x2c\xca\x7f\xce\xce\x71\xe5\x70\x8e\x8e\x7e\xd2\x73\x63\xb3\x6c\x64\x87\xed\xb8\xd5\xa9\xbd\xdb\xec\x96\x3a\xc5\xee\x1d\x4a\x18\x63\xaa\xfd\x6b\xb1\x75\xa3\x90\xb8\x29\x3b\x58\x07\xa8\x06\x6a\x96\xc2\x8e\x7b\x6f\x8f\x00\x3b\x8c\x68\x13\x7f\xb8\x06\xd7\x8e\xb7\xfd\xff\xec\x83\x18\xed\x95\xd5\x5b\xaa\x87\xb9\xd9\x02\x73\x7f\xef\xba\xd0\x14\x25\x1a\xe1\xbd\xe1\xd6\x1a\xee\x8f\xf7\xb7\x35\xd4\x6b\x5e\xae\xb9\xfc\x8d\xfe\x7a\x57\x0d\x6f\x6f\xed\x82\x80\x6f\x84\xb7\x86\xfb\xda\xc3\xed\x2e\xad\x15\x63\xb8\x77\x20\xc1\x07\xc2\x5d\x3c\xc6\xdb\xfb\x7a\xfb\x9f\xe2\xfd\x03\xb6\xb2\x27\x7e\x1a\x02\xbe\x17\x78\xdc\x7f\x9a\xfb\x1b\x07\xfa\xe3\x8d\xb4\x98\x97\x43\x0c\x72\xe5\xc2\xd4\xd6\x94\x72\x73\xe3\x26\x6f\x71\xbb\x16\x3c\x95\x75\x1d\x9a\xd3\x9b\xae\x76\xb9\xae\x9e\x6c\xae\x70\x39\x7c\xaf\xbb\xab\x7c\x81\xc6\x67\x35\x9f\x36\xee\x77\x38\xdd\x1d\x1e\xaf\x7b\xce\xe5\xe6\x1e\xe7\x82\xbb\xa6\xb1\xcd\xc2\xba\xaf\x36\x35\x57\xb8\xd5\xda\xd7\x5d\x55\xdc\xdb\xe2\x4f\x3b\xbd\xae\x4b\xf5\x0e\xc7\x85\x9a\x8a\x39\x97\x87\xbf\x78\x61\x7a\xfa\xce\xf4\xf4\x16\xcd\xfa\x82\x0d\x81\xb8\x56\xa3\x35\xa4\xb9\x73\xb8\xda\x7d\xa5\xc5\xe7\x71\xcd\x57\x54\x0d\x3b\xb5\x91\xa0\xb3\x46\xab\x8a\x7b\x5b\x02\x5e\x5e\xe5\x32\xb1\x27\x9b\x45\xd4\x55\xe5\xaa\x4f\x5b\x50\xaf\xdb\x6d\x42\x9d\xa9\x16\x40\xaf\x9a\x40\xab\x0a\x99\x7a\x82\xff\x2b\xf3\xb2\xd3\xac\x8b\x79\x3e\x36\xf4\x96\xba\x2a\x55\x8d\x46\xea\x10\xba\x76\xbd\x35\x4c\x11\x19\xe8\x89\xfb\x9d\xb6\x3c\x70\x44\xbe\xc8\x2d\xf9\x67\xc1\xc6\x97\x1b\x83\x5c\xf8\x5f\xf6\x0b\x7e\xca\x22\x96\xea\xb4\x29\x58\x9a\x8f\x1f\xaa\x0f\x43\x1e\xe1\x29\xaf\x7b\x7b\x7b\xb7\xd5\x3f\x53\xab\x91\xd7\x10\xf2\x7a\xb2\x52\x53\xcd\xbc\xc6\xb8\x16\xe4\x09\xce\xeb\x35\x4a\xa5\xde\x1a\x53\x12\x8e\xa0\xd2\x58\xef\x6a\xf4\x2b\x5f\xfd\xfa\x4f\xef\x39\xde\xfd\xe2\x1d\xde\x6a\x0c\xd5\x7f\x36\xfb\x5a\xfa\xbd\x85\x11\x65\x78\xe9\xdd\xfb\xef\x94\x06\xd5\xb1\xcf\x1a\xf8\xef\xcd\xbf\xa7\xdc\xfb\xeb\x3f\xd6\xde\xd9\xfd\x93\x53\x9d\x0d\x9f\x8d\x25\x6e\xdf\xfd\xd6\xbb\x2b\x43\x8e\xe4\xdc\xbd\xab\xaf\xcd\x7e\xd6\xb0\x5f\x4f\x75\x6a\x15\xa2\xd1\x01\xbb\x28\x23\xaa\xa7\xb6\x7a\x4d\x0f\xa1\x62\x7a\x13\xce\xc6\x78\x50\x89\x27\x94\x9e\x78\xd0\xa9\xc2\x89\x70\x02\x55\xa0\x9e\x98\x4a\xed\x36\xa5\xa6\x1c\x55\x27\x82\xe1\xa1\x90\x33\x6c\x5c\xb9\x7c\xb9\xbb\xd5\xd5\x3a\xd8\xd1\x52\xef\xd1\x3e\x7a\x43\xbe\xe9\xd8\xfa\xe4\x4e\x32\x75\xed\x5a\x2a\x38\x98\xec\x1f\x6c\x6d\x56\x9a\x82\x4d\xf8\xf3\x87\x7b\x87\x12\xc3\xfc\x67\x99\x37\x80\x51\x5e\x67\x1a\xed\xdb\xd1\x85\x13\xa3\x96\xc5\xd9\x05\x9c\x0c\x37\xd9\x4b\xac\x76\xa4\xe6\x2b\xd9\xe9\x89\x54\xe2\x7c\x9f\xa8\x77\x29\x1a\x02\xa1\xb9\x28\x15\xbd\x70\x83\x0f\xc4\x07\xb4\x86\x7a\x6e\xb9\xd8\x0e\x17\xa1\x54\x12\x9c\xaa\x38\x1e\x74\x34\x52\xa8\xc2\xbd\xfd\x71\x3f\x98\x18\x4f\x28\x7e\x27\xe5\x2d\xdc\xde\xdf\xd7\xdb\xee\xef\x89\x27\x78\x63\xbc\xfd\x00\x32\x79\x6b\x68\x32\x3a\xc2\xc7\x1c\x9d\xc9\x50\xb8\x4d\x55\xbe\x4a\x1b\x1b\x4d\x73\x47\x95\x4f\x60\x67\xda\x99\xd8\xa5\xf4\xf8\xc9\xb3\x3e\x97\x3e\x18\x16\xbe\x1a\xfe\xe5\x8f\xa8\x38\xef\x4c\xf3\x3f\x30\xfd\xff\xe8\x55\x9e\x4a\xc4\x26\xcf\xdf\x8a\xaa\x6d\x6d\xa1\xd1\x0e\xc7\xd8\x84\x3d\xff\xa2\x3a\x6a\x18\x3f\xf4\x37\xf3\xea\x06\xdf\xb5\xdd\xe7\x93\xd7\xae\x25\x11\x89\xc1\xde\xb0\xbf\xa9\xa5\x59\xf1\xfb\x9a\x3d\x0a\x62\x31\x98\x6c\x51\xfe\xc8\x2a\xf8\xdd\x5f\x67\xdf\x50\x5e\xfd\xf3\x2d\xed\xad\xbf\x8b\xc4\xf8\xa8\xfa\xf4\x35\x5f\x43\x75\x53\x13\xb7\xa7\xed\xde\x7f\x5f\x7d\x4b\x15\xac\x91\x05\x91\xab\xe0\xc9\x6a\x27\x72\x15\xea\xeb\x69\xb0\xd3\x55\xdb\xdb\xdf\x13\x8a\xfb\x4f\x71\xbd\x2f\x54\xcb\x5d\x7d\x21\x7c\xf9\x6f\x66\x86\x3a\x77\x4b\x1d\xc3\xc3\x1d\xfc\x6e\xe7\xd0\xcc\xee\x8a\x2a\x7e\xb4\x9b\xe0\x7f\x39\x3b\x4b\x3a\xe5\xd3\xce\xa1\xa1\xce\x7b\xf7\xbe\x1c\xe5\xe3\x7f\xb5\x75\x6f\x8b\xd9\x3d\xa2\x7c\xaa\x64\x58\x25\x2c\xe9\xe8\x91\x96\x26\x5f\x95\x83\xa1\x47\x70\x28\x58\xa6\x60\xa8\xcf\x1c\x43\xa6\xa6\xf6\x90\x5e\xd9\xf6\xb7\x04\xeb\xbf\xfc\x4e\x7d\xb0\xc5\x4f\x3f\x25\x43\xf2\x43\x1d\xbf\x1b\xec\x08\xe2\x6f\xd6\x22\xbb\x5f\x58\xd4\x7c\x5f\xec\xfd\xa7\x7a\x42\xad\x84\x4d\xed\xc3\xe6\x0a\x0e\x7b\x66\xcf\x61\x30\xb3\xdf\x77\xd0\x9d\x18\xe8\x80\x6a\x6c\x40\x1f\xaa\x27\x84\x7f\xc7\xea\xa7\x1d\xb3\xb3\x76\xac\xb6\xda\xd9\xef\xbe\x5f\xfa\xa1\x6d\xf8\xe5\x81\x96\xe0\xb4\x45\xb2\xf7\x6b\xe5\x0b\xe5\xf7\xd9\x19\xd8\xf3\x3b\x38\xd5\x3d\x0e\x4f\x34\x9a\x8b\x86\x70\xef\x53\xbc\x9d\x86\x7e\x1c\x8a\x03\x34\xd0\x31\x88\xbe\xfb\xc2\x7b\xc5\x67\xf8\xee\xdf\xc7\x70\xc5\x47\xd4\xf7\x50\xf6\x7a\xef\xdf\xf7\x96\xfc\xc4\x7c\xf0\x81\xf7\x71\xa0\x37\x46\x00\xf3\xbd\x86\xdf\xe7\x0b\xdf\xe8\x79\xc9\x3b\xfc\x1f\xac\x52\xdd\x21\x97\xfe\x76\xf3\xfd\xb4\x45\xd7\xc4\x41\x67\xe0\x85\x6e\x5f\x93\xcc\x67\xac\x77\xac\xa3\x0b\xde\xef\x3a\xba\x0f\xbd\x65\xad\x8f\x87\x56\x52\x71\xeb\x50\x71\x93\x50\xbf\x69\x51\x42\xab\x6f\x51\x56\x6d\x7d\xad\x8d\xfe\x26\xfb\x15\xef\xe0\x0b\x7c\x57\x89\x2b\x2b\xca\xb7\x95\x5f\x58\x36\x98\x07\x17\x24\x6d\xff\x8d\x83\x3b\xcb\x3a\xc6\xd6\xca\x92\xfd\xd4\x09\xf6\x4f\x07\x76\xfb\xd8\xfe\x9b\x9e\xc3\xcf\x3e\x9b\x57\x98\x8b\x5d\xb4\x79\x15\xfa\x51\x9b\x77\x80\xbf\x62\xf3\x4e\xd4\xd7\xb4\xcd\x6b\xd0\xbf\x64\xf3\x1e\x16\xc1\xa5\xcd\xe2\x2b\x59\x1d\x7b\x8f\x6e\x0b\x8e\x0a\x48\xb7\xd9\x07\x36\xcf\x99\x8f\x7b\x6d\x5e\x61\x35\xfc\xb4\xcd\xab\xd0\x47\x6d\xde\x01\xfe\xa2\xcd\x3b\x99\x9f\x5f\xb5\x79\x0d\xfa\x82\xcd\x7b\xd8\x4d\xbe\x6e\xf3\x95\x2c\xcc\x7f\x92\x5a\x2d\xbd\xb2\xb6\x38\xbf\xb0\x21\x3a\x52\x67\x45\xbc\xfb\x5c\x9f\x98\x79\x45\xac\x42\xb5\xb8\x92\x5f\x12\xf9\xcd\x8d\x85\xd5\xb5\x75\x31\x22\xe6\x56\x57\x36\x8a\x4b\x4b\xab\xb1\xc2\xea\xf2\x3e\x3f\x55\x9c\xdf\x5c\xca\xaf\xed\x8b\xfb\xf4\x66\x71\x6d\x7d\x71\x75\x45\x9c\x8b\x75\xef\xab\x26\x8a\x2b\xc5\xb5\xfc\x46\x71\x96\x56\x5f\xbf\x33\x1f\xdf\xd8\x98\x13\x73\x6b\xab\xcb\x62\xdc\x46\x88\xd2\xda\xea\xed\x62\x61\x23\xb6\xb0\xb1\x51\x1a\xea\xea\x3a\x6c\x8f\xa5\x70\x3f\x2d\xb1\x57\x70\x93\x5d\x44\xa8\x16\x70\x6b\x15\x38\xbe\x53\xec\x2c\x68\x1c\xf7\xd9\x73\x48\x84\x60\x33\x40\x08\x20\x2d\xd4\x22\x6e\xb7\x79\xdc\x6c\x05\xc6\x4d\x3c\xb1\x60\xce\xac\x43\x1e\xc1\xef\xe8\xed\x37\xc6\x0a\x18\x97\x1f\xd3\x3f\x7a\xa3\x3e\x3a\x7b\x54\x3e\xfe\xb6\x7d\x14\x35\x01\x6e\xc5\x44\xe6\x4d\xed\xec\x81\xef\xeb\xec\x0e\xac\xc5\xa1\xdd\xc0\x53\xe4\xe5\x9a\xe9\x95\x60\xe3\x47\xd6\x10\x88\x07\xcd\xdd\x86\xa6\x00\x7d\xcc\x8c\xca\x06\xb4\x43\x78\xcd\x77\x3d\x71\x7f\x76\x85\x5b\x75\x77\xfc\x07\x7a\xae\x70\x95\x3b\xb8\x93\x6b\xdc\xc5\xdd\xbc\x82\x7b\xd4\xc2\xea\xbc\x1b\xf9\x58\x2c\xad\x2f\xae\x6b\xeb\xc5\xfc\x5a\x61\xc1\xb1\xb9\x5e\x5c\x73\xd2\xb0\xae\x2d\xad\xce\xaf\x6e\x6e\x38\x96\x8b\x2b\x9b\x8e\xd2\xd2\xe6\xba\x56\xc8\xaf\x14\x8a\x4b\x56\x9f\x70\xdc\x6e\xbd\x87\x4d\x48\x66\x08\xc9\x9e\xcb\x8c\x65\x85\x98\xfc\x84\xd5\x5c\x9f\x94\xda\x8d\x5b\x19\xd9\x1b\x90\x1d\xd9\xdc\x9c\xd8\x7e\x2e\x23\x95\xb6\xfc\xf7\xdd\x68\x93\x42\x41\x9f\x09\x84\x42\x92\x65\x25\x4b\xe9\xa3\x0f\xb0\x5e\x2a\x97\x8c\x4a\x6e\x48\x91\x9b\x8b\x4a\xc5\x10\xb3\x42\xfe\x20\x2d\x1d\xe1\x5b\x0f\x3a\xb8\x27\x35\x56\x18\x9b\x7a\x3e\x13\xd2\x43\x81\xed\x8c\x90\xe9\x74\x26\x24\x47\xb2\x01\x21\x07\x89\x1b\xcc\x66\x45\xd9\x02\xe5\x67\x65\x07\x54\xb6\x24\x64\x37\xcd\x77\x13\xf2\x07\xe9\x8c\x80\x13\xdb\x79\x21\x3d\xe9\x4c\x0e\x1a\x41\x73\x1e\xe2\xfa\x89\xeb\xcf\x05\x72\xd9\x6c\x36\x20\x79\x24\x9b\xd5\x25\x4b\x67\x8a\xd9\x6c\x54\xaa\x86\xc0\x3a\x8e\xb6\x3c\x1c\x72\xa6\xd2\x19\xe9\xd4\x93\x52\xd3\x93\x70\x3f\x2b\x79\x2e\x2a\x1d\x86\x0e\xbf\xc4\x6c\xd9\x39\x93\x14\x34\x63\x19\xa7\x51\xb2\xdc\x58\x41\xaa\x9d\x21\xe8\x53\x62\x5b\x6c\x63\xed\x72\xb7\xb3\x0d\xdb\xba\x9e\xc9\xa5\x03\xf9\xa9\x6c\x46\xcf\x62\x76\xe4\x46\x06\x53\x01\xda\x94\x6d\x39\x2a\x9d\x86\x74\xa5\x22\x0f\x90\x5a\x33\x34\x1a\x44\x3d\xa9\x23\xc4\x7a\x32\x2f\x95\x99\x39\xc9\x0b\xb0\x2f\x9d\x9d\x51\xe9\x32\x04\x39\x59\x99\x2a\x7c\xe2\x60\x33\x82\x56\x90\x23\xb9\x2c\x41\x72\xa3\xa6\x93\x6e\xe3\x81\xab\x92\xa5\xc6\x92\x9d\xa1\x83\x60\x57\x18\x8f\x06\xdf\x63\xad\xc2\x23\x70\x21\x85\x1d\xe7\xc4\xd8\xb6\x9e\xa7\x44\x98\x91\x62\x01\x8a\xa6\x14\x01\x38\xb9\xef\xa5\x54\xdb\xf4\xfc\xa8\x65\xa2\xf2\x09\x8f\xcb\x33\x78\x8a\x05\x1e\x6e\xed\xf0\x43\x55\x86\xb9\xa1\x07\x95\x1e\x75\x2c\x13\x0a\xe8\xa1\x6c\x67\x28\x2a\xab\x8d\xb2\xa2\x8c\xc9\xd9\xfc\x68\x54\xd6\x18\x00\x0a\x21\xab\x52\x97\xe9\x71\x30\x7a\x32\x2b\xab\x49\x9a\x82\x54\x0d\x29\x2a\xbd\x58\xc6\x67\x86\x44\x20\x02\x05\xd8\x95\x35\xa9\x9c\xd8\xce\x09\x59\x83\xa0\x45\xa5\xcf\x98\x9c\xce\x94\x1d\xb3\xa3\xd9\x33\xb2\xba\xa8\x6f\x45\x65\xad\x31\x79\x3d\x33\x79\xc3\x52\x06\x42\xd0\xd7\x99\xfa\x13\x46\x99\x79\x53\xcf\x65\xca\x5e\x6f\x4a\xf2\x7c\x52\x7a\x23\x54\xa4\x28\xdd\x64\xb9\x8a\x86\x6a\x0c\x92\xfb\x91\x09\xb5\x2d\x9d\x29\x53\xf0\xb0\xdb\xe4\x36\xd2\x4b\x66\x3b\x43\x3a\x1e\xdb\xe7\x03\xd6\x3c\x3d\x82\xda\x27\x4d\x16\x3b\x99\x80\xff\x13\xd0\x3e\x9a\xaa\x27\x24\xb0\xcc\x58\x9d\x8e\x68\xa1\x9a\x12\x0f\x38\xe7\x66\xae\xea\x0c\x56\x66\xca\xd8\x74\x46\x7a\xf5\xa4\x18\x93\x95\x28\x4a\x0f\xe2\x9b\x4b\x8a\x1c\xcc\x7f\xcf\xe7\xe3\xf8\x9f\x3f\x99\xdc\xce\x95\x4f\x68\x11\xb9\x16\x09\xb4\x22\x4c\xf5\xd8\x5b\x5d\x24\x2a\x1b\x8c\x32\x27\xea\x47\x9c\x89\x36\x1a\xb8\x3f\x83\x36\x19\x65\x07\xd1\x93\x46\xd9\x49\xb4\xd9\x28\x6b\x44\x03\x46\xd9\x45\xb4\xc5\x28\xbb\x89\x9e\x32\xca\x15\x44\x83\x06\x93\xd5\x91\xdf\xc2\x91\xd3\x70\x24\x88\x05\x04\x1c\x21\x1a\x82\x23\x44\x5b\xe1\x08\x51\x1d\x8e\x10\x3d\x03\x47\x88\xb6\xc1\x11\xa2\x61\x38\x42\xb4\x1d\x8e\x10\xed\x80\x23\x44\xcf\x1a\x62\xd8\xac\xa7\x4e\x03\x66\x7d\x39\x91\x42\x12\x72\x29\x33\xe6\xe8\x91\xb3\x54\x54\x11\x43\x76\x46\x64\x27\xda\xc5\x40\xa5\x4e\x88\x27\x84\x5b\xcf\x0f\xea\x74\x56\xfd\x8f\x08\xd4\x4b\x54\x46\x0f\x72\xc0\xfd\xd2\xe8\x94\xbc\xa1\xdb\xdc\x5c\xec\x70\x54\x1e\x9d\xea\x32\x44\x9f\xe9\x67\x37\x30\x7c\xec\xf1\xc5\xd1\x3e\xc7\x1a\x25\x3d\xf3\x7f\x64\x1e\xb4\xa3\x09\x7d\xb0\xdc\xc5\x1b\xb0\x93\x73\xd8\x37\x1c\x3d\xde\x4f\x54\x6d\x7e\x30\x2a\xe3\x46\xac\x71\x38\x2a\x7b\xfe\x37\x28\x2a\xac\x00\x78\x2f\x52\xc1\xfc\x6d\x22\x26\x26\xa8\x33\x11\xc2\x67\xb6\xb7\x27\xf4\x09\xb4\x72\x06\x67\x36\xce\x3c\xb4\x6b\x0f\xc7\xad\x16\xf6\xfb\x70\x84\xf8\x51\xfd\xf8\x33\x21\xb2\x22\x15\x29\x6e\xc7\x74\x21\x86\xb7\xb1\x56\xff\xc3\x69\x11\xb3\xd6\x90\x0e\xac\x09\x94\x90\x39\x6a\xe6\x91\xeb\x99\x0f\x15\xa1\x8a\xc0\x87\x4a\x58\x6d\xce\x26\xe9\x80\x73\xe3\xa8\xd4\x4d\xb4\x3e\x8e\xd6\x4a\x1d\xed\x93\x1c\x1d\x32\xd6\x49\xae\xa4\x72\xb3\xba\x54\x53\xf9\x59\x4c\x2b\xa9\x7c\x00\x7c\x8e\x0e\x98\xa3\xcf\xe4\xe1\x12\x4e\x5d\x7d\x1c\xb9\xd3\x61\x61\x1c\xfb\x02\x31\xad\x60\xbd\x63\x8c\xe8\xd6\x51\xe6\x40\xf7\x22\xf6\x4e\x14\x92\xf3\xb1\x55\xb1\x22\xed\xa8\xcd\x74\x02\x63\xda\x3a\xc2\x1e\xda\x42\xca\x07\x28\x06\x02\x1a\x67\xd8\x8e\x81\x3e\x8c\xd0\x0c\x9a\x6a\xe9\x46\xd3\x08\x31\xae\x4f\x90\x31\xca\xd6\x79\x33\x64\xb4\x01\x3b\xa2\x6c\x3a\x13\x13\xc3\x78\xf1\x91\xc7\xb6\x52\x90\x2f\xfb\x21\xd7\xda\x20\x3d\x73\xf8\xd5\x6a\x25\xea\xb8\xca\xb5\x33\xa3\x53\xf9\x0e\xd9\x1e\xa4\xf6\x53\x93\xa3\x77\xef\xd1\x2d\xee\xa7\xf2\x82\xa1\x8b\x18\x45\x6d\x1c\xa7\xee\x70\x36\x56\x8e\xf0\x7a\x34\xde\xf0\x81\x3a\x7d\x58\x7d\xf1\x51\xf4\xb1\x98\x84\x21\xfb\x22\xc7\x2e\xfa\x94\x21\xfb\x23\xdb\x30\x4c\xc5\x02\x6f\x1f\xc7\x20\x2d\x31\x19\x01\x74\xe4\xa0\xc2\xf6\xa3\x4b\xc5\xa5\xa3\xd4\x63\x68\x12\x6b\xb9\xa7\x71\x58\xe0\x80\xfe\x2d\x4a\x71\xe2\xff\xaa\xfa\xc8\x7d\x3a\x57\x86\x75\x1c\x1d\x87\xf2\x1d\xca\xda\x3e\x26\x29\x18\xfb\xfb\x4f\xd1\xfe\x43\xba\x1d\x00\x7b\x1f\x07\x5b\x1e\xc5\x96\x1b\xac\xe6\xc4\xab\x1b\x7d\x58\x17\x93\xe7\xd0\x8b\x63\x4f\xd0\x8f\xe3\xac\xe5\xf5\x75\x32\x0e\x7e\xc2\x90\xbd\x20\x97\x28\x6a\x63\x88\xab\x18\xc7\x7b\x6a\x3f\x4e\xcf\x18\x54\x8e\xf2\x12\xd8\xcb\xc6\x03\xc6\x9e\x06\x33\x09\x86\x13\x73\xc5\x78\xc0\x4d\xcd\x55\x30\xa6\xe6\x1a\x61\x92\x60\x9e\x25\x0c\x31\x69\xc2\x10\x73\x9d\x30\xc4\x4c\x11\x26\x01\xe6\x06\x61\x88\x99\x26\x0c\x31\xcf\x11\x86\x98\x9b\x84\x19\x01\xf3\x3b\x84\x21\x26\x43\x18\x62\xb2\x84\x21\xe6\x16\x61\x52\x60\x9e\x27\x0c\x31\x2f\x10\x86\x98\xaf\x10\x86\x98\x17\x09\xf3\x14\x98\x97\x08\x43\x4c\x8e\x30\xc4\xe4\x09\x43\xcc\x8c\x21\x07\x0e\xc2\x5c\x20\x41\x5e\x00\x37\x6b\x72\xc3\xe0\x8a\x66\x3d\x41\xb8\x08\x61\xce\x90\x83\x07\xe8\x79\x12\x4c\xf4\x82\xc9\x11\x7a\xd1\xe4\x08\x7a\xdb\x90\xe7\x0f\xa0\x2f\x93\x60\x42\x97\x4c\x8e\xa0\xcb\x26\x47\xd0\x15\x43\x0e\x1d\x40\x57\x49\x30\xa1\x25\x93\x23\xe8\xef\x9a\x1c\x41\xd7\x8c\x0f\x2b\x1c\xca\xfe\xcd\x28\x19\x91\xee\xa2\x54\xcf\xa4\xb7\xe8\x7d\x12\x65\xb8\x64\xff\x78\x0a\x17\x10\xfe\x2e\x0e\x65\xab\xf7\x4b\x65\xe6\x4c\xe2\xc2\xd0\x69\x51\xf7\x23\xf4\xfb\x78\x77\x54\x1c\xe6\x54\x36\x5a\x3e\xc3\xdf\xbe\x8e\x3a\x7d\x3b\x53\x56\x67\x47\xcb\x61\x92\xfe\xc2\xfd\x26\xfe\x97\x1c\x79\xbb\x80\x1b\x13\x20\xb8\x13\x67\xcb\xac\xaa\xf3\x13\xbe\xf7\x35\xe9\xf8\x43\xbc\x1d\x46\xd9\x7f\x03\xf9\xb4\x1b\xf4\xfc\x18\x00\x00" - -func font_fontello_eot_gz_bytes() ([]byte, error) { - return bindata_read( - _font_fontello_eot_gz, - "font/fontello.eot.gz", - ) -} - -func font_fontello_eot_gz() (*asset, error) { - bytes, err := font_fontello_eot_gz_bytes() - if err != nil { - return nil, err - } - - info := bindata_file_info{name: "font/fontello.eot.gz", size: 3543, mode: os.FileMode(438), modTime: time.Unix(1432348676, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _font_fontello_svg_gz = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x0b\xad\x57\x6d\x6f\x1b\x45\x10\xfe\x8e\xc4\x7f\x18\x8c\x84\xe0\xc3\xda\xfb\x72\xfb\x72\xd0\xb4\x88\xb4\xaa\x90\x10\x54\xa2\x80\xf8\x68\xec\x6b\x6c\xe9\x6c\xc7\xf6\x26\x69\xfb\xeb\x79\x9e\xdd\x73\x93\xd8\x69\x29\x14\x29\xb9\xdd\x9b\x9b\xb7\x7d\x66\x76\x66\xfc\xe8\xc9\xeb\x55\x2f\xd7\xdd\x6e\xbf\xdc\xac\xcf\x46\x66\xac\x47\xb2\xcf\xd3\xf5\x7c\xda\x6f\xd6\xdd\xd9\x68\xbd\x19\x3d\x79\xfc\xf9\x67\x8f\xbe\x78\xfa\xcb\xf9\xcb\x3f\x5f\x3c\x93\xfd\xf5\x85\xbc\xf8\xed\x87\x9f\x7e\x3c\x97\x91\x9a\x4c\xfe\x70\xe7\x93\xc9\xd3\x97\x4f\xe5\xd7\xdf\x9f\x8b\x19\x9b\xc9\xe4\xd9\xcf\x23\x19\x2d\x72\xbe\xfc\x76\x32\xb9\xb9\xb9\x19\xdf\xb8\xf1\x66\x77\x31\x79\xbe\x9b\x5e\x2e\x96\xb3\xfd\x04\x8c\x13\x32\x42\x68\x02\x65\xc6\x8c\xe7\x79\x3e\xa2\x0d\xaa\x86\x37\xeb\xfd\xd9\x03\xf2\x56\x6b\x4d\xfe\xc2\xb9\xea\xf2\x74\x3e\xcd\xd3\xc7\xe7\x9b\xcb\x37\xbb\xe5\xc5\x22\xcb\xd7\xe7\xdf\x88\xd5\xc6\xcb\x5f\x6f\x64\x03\xd2\x72\x3d\xed\x65\x7a\x95\x17\x9b\xdd\x5e\xbe\x97\x57\x9b\x75\xee\xfa\x7e\x33\x9e\x6d\x56\x8f\x26\xef\xe4\xa1\x6b\xde\xbd\xda\x73\x25\x87\x2c\xe7\x67\xa3\x03\xeb\x48\x20\xbb\x7c\xab\xa6\xf3\x6b\xf5\x1a\xd0\xc0\x81\x91\x1c\x38\xd5\xab\xe9\xac\x93\x61\xb7\x5a\xf6\x6f\xee\xca\x15\xf2\x4d\x47\xbf\xce\x46\x0d\xc5\x0a\x65\x9f\x77\x5d\x9e\x2d\x08\xea\x6e\x35\xed\x47\x72\xb5\x5e\xe6\xbd\xba\xec\x76\xaa\x5b\x1d\x0c\x4c\xf7\xb3\x6e\x0d\xb1\xe4\xf1\x32\xef\x86\x37\x65\xf8\x3a\x29\x67\x5f\xee\xf7\xcb\xf5\x85\xba\xe8\xdf\x5c\x2e\x1e\x72\xb1\x70\xd5\xaf\xe5\xa9\xd6\xd3\x15\x22\x39\xdb\x5c\x14\x8b\xb3\xcd\x1c\x6f\x5f\x7d\xf9\xba\x4b\x5a\x7f\x07\x1b\x67\xa3\x95\x8f\x46\x9c\xd7\x5b\x2d\xbe\x55\x8d\x11\xa3\x4d\x56\x78\x48\x63\xb9\x28\x2c\x75\x37\x10\xa4\x12\xa5\x52\xa4\x4a\xbc\x95\x95\x4d\x41\x82\xb9\x56\xc6\x36\x5b\xad\xa2\x6a\x94\x71\x50\x64\x54\xec\x21\x86\xb7\xb0\xc5\xaa\x9c\x56\xd6\x28\x0f\xa9\x56\xd9\x48\x9b\x31\x4a\x50\x90\x2d\xfc\x1e\x4f\xf0\xf9\xc2\xe4\x55\x80\x2f\xde\x29\xd7\x6e\x55\x14\xad\x4c\x23\xbe\x2f\x02\x7a\xab\x2c\x79\xa1\x89\xac\xd0\x02\xf9\x50\x0c\xd1\x94\xb2\x60\x0e\x8b\xe2\x8c\x4a\x83\x64\x86\x15\x63\xe1\x0d\x16\x0d\x2b\x30\xdf\x2a\xaf\xc5\x1a\xe8\x6c\x15\x75\x06\x3a\xd0\xe0\x31\xc8\x04\x15\xb5\x84\x46\xb5\x56\x5a\x68\x16\x8f\x7f\xe3\x04\x34\xf1\xd0\x25\x89\x0f\x9b\xc4\xc5\xec\xb4\x34\x9a\xae\xe3\x5d\x59\x27\xde\xf3\xdc\xc0\xc9\xd3\x77\x03\x24\x24\xe2\x30\x10\xbf\x2e\x10\x49\xa4\x0a\x97\x0d\x76\x3d\xfc\x16\x00\x94\xc4\x42\xdc\x0a\x0f\xe5\xc4\x59\xf8\x24\x31\xc2\x6d\xfe\xc3\x1d\xc4\xa8\xda\xa5\x15\xbc\x78\x00\x91\xbd\xa3\x61\xc0\x03\xaa\xf2\x3d\xf9\xf5\xd6\x16\x3f\xcb\xe1\xa4\x95\x08\x69\xf8\x00\x23\x6e\x10\x35\x7e\x41\x2f\x8a\x94\x53\x4d\x8e\x80\xaa\x87\x3c\x81\x81\xff\x2d\x44\x81\x6b\x9f\x34\xa1\x2e\x46\xa1\x4d\x0a\x3b\xe0\x91\x08\xd7\x80\x9e\x55\xad\x17\xbe\x33\xd8\x40\x2c\x10\x7c\x10\xf9\xb0\xad\x72\x29\x33\xde\x88\x1e\x84\x80\x92\x45\xb8\x3c\xce\x8a\x3c\xf2\x5b\x58\xc4\x49\x54\xcc\x94\x7d\x7b\x74\xe1\x92\x8f\x63\xf3\xde\x74\xc6\x4d\x5b\x5e\xee\x97\xfb\x93\x9c\x36\x43\x4e\x5b\x60\xd5\xb8\x16\xc9\xa8\x23\x92\xd1\xd2\x60\xf5\x26\x61\xb7\x28\x64\x22\x0c\xdf\x10\x41\x24\x06\x52\xc2\xa5\xeb\xc2\x0d\x2f\xa5\xbc\x66\x7e\x0b\x0b\x12\x11\x12\x2d\x94\x0d\xb9\x28\x1a\xd2\x5d\xdf\x35\x10\x4e\x0d\xd8\x3b\x06\xfc\x7d\x03\xfe\xc8\x80\xbb\x35\x10\xfe\x9b\x81\x8f\x3f\x41\x31\x70\x04\x78\x4c\x7e\x1c\xdf\x0b\xf8\xbe\x9b\xee\x66\x8b\x13\xb8\xed\x00\x77\x68\x90\xac\x29\xc0\x32\xd2\x47\x45\xa4\x5e\x0c\xf0\x08\x59\x17\x11\x5c\x24\x24\x96\xe8\x2a\x81\x0b\x52\x91\x44\x27\x95\x22\x45\x22\xd6\x33\xab\x26\x78\x1e\xb8\xe5\x99\xbd\xc6\x8d\x61\x22\x6e\x91\x47\x38\xeb\x70\x59\x4d\xcb\xf2\x61\x58\x4f\x90\x73\xe4\x74\x5c\x12\x59\x0c\xae\x83\x63\x05\xc3\x4d\x4a\x8d\x4a\x50\x8d\x42\xe1\x20\x50\x3e\x60\xc1\xad\x25\x91\xb5\xc0\x97\xed\xbb\x0f\x85\xcd\x06\x0a\x25\x26\x32\x30\xc4\xbd\xf5\x16\xfe\x98\x6a\x02\x96\x7a\x58\xa6\x07\x5b\xcb\xca\x23\xa5\x98\x1d\xa3\xd9\xda\x34\x0e\xef\x45\xf3\x6a\xdf\xed\x4e\xb0\x74\x03\x96\x91\x65\x14\x50\xe2\x7e\xa1\x1a\xe3\x84\x44\x52\x27\x5c\xa2\x85\x6a\x52\xda\xf2\xde\x69\x52\xc4\xb5\xb9\xd6\x6b\x02\x0f\x78\x50\x36\x52\x4e\xa8\xc1\xcc\x2e\x14\x0e\x94\x00\x14\x08\x87\x9b\x80\xfb\x99\xc8\x11\x50\x38\x0c\x6e\x33\xbf\xe1\x44\x19\xfa\x2d\x6b\x29\x9f\x11\x77\xdf\x96\x48\x58\xaa\x00\xa5\x29\x4f\x16\x12\xbb\x75\xac\x3d\x01\x49\x68\x72\x93\x18\x0b\x87\x6a\xe8\xa9\x06\x26\x70\x25\x60\x2e\x29\x8a\x29\xcf\xdc\x45\x8c\x5b\x69\xda\x84\x63\x24\xd0\x11\x73\xcf\x90\xa0\xac\x95\x3d\x2c\x00\x4d\x56\x31\x53\x7c\xf2\xf5\x3f\xf0\x5e\x90\x45\x2a\xd7\xbf\xcb\x51\xa2\x7a\x5a\x11\x9a\x01\x56\xe7\x6a\x97\x53\x2d\x6e\x0c\x2a\x7b\x52\xd1\x2c\x54\x44\x6d\xc6\x31\x34\x5b\x8a\xb5\x99\xf1\x0f\x25\x8d\x5b\xc0\xd2\x96\x85\x07\x67\xa7\x31\xd9\xa3\x86\xa1\x23\xa0\xc9\x00\x0f\xf4\x07\x40\xc6\xda\xe9\xd8\x7f\xb0\x30\x2c\x31\x01\x6c\x68\x77\xc0\xc0\xb7\x00\xca\x97\x48\x86\x1a\x49\x7f\x1c\xc9\x74\x1c\x49\x7f\x12\xc9\xa6\x04\x03\x91\x44\xe9\xf6\xc7\x91\x0c\xf7\x22\x19\xd8\x4c\x19\xc9\x50\x22\x59\xfa\x04\xd3\xa0\x46\x32\x94\xaa\x00\xcf\x19\x7e\xe2\x8b\x48\xc6\x12\x49\x7f\x88\x64\x53\x22\x69\xee\x47\xd2\x47\xe8\x42\x4f\xc6\xe5\x6b\x87\x41\x20\x1f\xe6\x82\x61\x28\xb8\x1d\x06\x86\xf1\x60\xd8\xf2\x43\xe5\x82\x22\xd7\x12\x28\x8e\x06\xa9\x1d\xb2\x60\xc8\x08\x5b\x33\xc2\xaa\x12\xff\x43\x1a\x3c\x94\x11\x45\x0f\xd0\xc6\xcd\x84\x9e\x06\xa0\xe3\x1b\xee\x07\x8a\x89\xb5\x35\x9a\x1e\x81\x43\x95\x6b\x00\x83\x21\x5c\xa1\x80\x86\x88\xb0\x73\xa1\xf0\xa1\x53\xe3\x8f\xdd\x2a\x96\x9e\xe5\x4a\x33\x47\x41\xb2\x88\x2f\x81\x66\xbe\x03\xd9\x96\x64\xf4\xb1\x96\x65\x49\x71\x44\x42\x8f\xfd\x34\x0c\x4e\x66\xca\x68\xc6\xcd\x7b\xd3\xb9\xdf\x5c\x6c\xae\xf2\x49\x3e\xfb\xc3\xd4\x86\xc9\x42\xf7\x2c\xb8\x5a\x5a\x26\x23\x33\x89\x1e\x36\xa5\x76\x46\x14\xce\x88\xb4\xd4\x3d\x08\xf8\x88\x34\x27\x4b\x64\x7a\xb1\x27\x4b\xa4\x70\xa4\x04\x1d\x25\xc1\x64\x7c\xb5\x6d\x5f\xf9\x1b\xf6\x0b\x68\xb0\x6d\xa6\x3a\xd3\xb3\xb2\x6a\x55\x4d\x09\xb7\x0d\x3d\x28\x3a\x39\xf8\x60\x5f\x82\x8c\xec\xb4\x81\x15\x1a\x41\x68\x99\x9f\x06\x93\x58\xe3\xf5\x41\x4c\xde\xed\xad\x3e\xa9\x9a\x1f\x98\x60\x57\xdd\xfa\xea\x04\x8c\x70\xe8\x3f\xd4\x8b\xb3\xd4\x26\x87\xf4\xf7\x19\x03\x07\x12\x9b\xcd\xda\xd7\x4d\x8f\x1a\x55\x80\xb0\x74\xda\xf9\x77\x5d\x99\xd9\xc1\xa7\x43\x43\xf0\x7d\x61\x62\xc8\xb9\x21\xa2\x1f\xc3\xff\x31\x86\xa1\x13\x2b\xa0\xff\x1f\xdd\x3c\xae\x8f\x1f\xc0\xef\xb2\xbf\x3a\x2d\x8e\xf1\x4e\xcf\x39\x1a\x97\xee\x0d\x1b\xd6\xd9\x6b\x3c\xdc\xed\xb7\x58\xbf\x85\xe3\x41\x24\x54\x67\xe3\x35\xb8\x8b\xdc\x47\x8f\x59\xb4\x41\x7e\xcd\xf9\xf7\x9f\xc6\x23\x7a\x63\x29\xf2\x89\x73\xcd\x6c\xba\x9e\x75\xfd\x09\x2e\xe9\x80\x4b\x29\x06\xf6\xce\x04\xd9\xf3\x77\x46\xe4\x2f\x99\x50\x09\x0c\x62\x3d\x1d\x7f\x57\x70\x88\xf7\x5c\xf1\xef\x1f\x66\xe2\xc4\x53\xe4\x59\x8e\x2a\x00\xe5\xd9\x57\xe9\x66\xd0\xd2\x3c\xc4\x52\x65\x0b\x5d\x2a\xda\xe5\xe4\xfd\x1d\xb1\x22\x7a\xca\x51\xbd\xe6\x7c\x5f\xda\x35\x63\x3b\x9c\xe7\x8e\xac\x2a\xb2\xb7\x3c\x1f\xc2\x72\xc2\x5f\xb5\x65\x73\xf8\x0d\xcd\x1f\xe8\x8f\xff\x06\xdc\x9f\x7a\xd4\x53\x10\x00\x00" - -func font_fontello_svg_gz_bytes() ([]byte, error) { - return bindata_read( - _font_fontello_svg_gz, - "font/fontello.svg.gz", - ) -} - -func font_fontello_svg_gz() (*asset, error) { - bytes, err := font_fontello_svg_gz_bytes() - if err != nil { - return nil, err - } - - info := bindata_file_info{name: "font/fontello.svg.gz", size: 1710, mode: os.FileMode(438), modTime: time.Unix(1432348676, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _font_fontello_ttf_gz = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x0b\xe5\x57\x5d\x6c\x5b\x47\x76\x9e\xb9\x97\xbc\xa4\xa8\x1f\x52\x16\x45\xc9\xa2\x4c\x0f\x75\x2d\x4a\x16\x2f\x29\x99\xfa\xb5\x2c\x33\x0a\x29\x4a\x8e\x65\x3b\xb4\xac\xb8\xa4\x93\x4d\x48\x51\xd4\x8f\xa3\x1f\x56\x92\x0d\xe5\x07\x41\xd0\xcd\x16\xa9\x90\xa6\x46\xb0\x30\x8a\x36\x05\xb6\x0b\x67\x51\xf4\x69\xe8\x64\x9b\x6c\x11\x20\x8b\xa2\x5d\x6c\x8b\x5d\xa0\x45\x83\x45\x1f\xfa\xb3\x0f\xfb\xe0\x45\xb7\xd8\x87\xb6\x0b\xf4\x21\x52\xbf\x73\xef\x95\x2c\xdb\x72\x0b\x2c\xfa\x56\x52\x9c\xf3\x9d\x33\xdf\x9d\x39\x73\xce\x99\x99\x2b\xc6\x19\x63\x0d\xec\x6d\xa6\xb2\xc2\xf3\xd7\x7a\x13\xc9\xee\x0b\xff\x0e\xcb\x2f\xf0\xbb\x5e\x5a\x2d\x56\xfe\xf6\xf8\xf1\x4f\x19\xe3\x13\xf8\x5d\x2c\xdd\xde\x12\xcc\xfc\xd4\xbd\x84\xc6\xb3\x50\x59\x5c\x7d\xf7\xce\x9d\x3c\xf4\x25\xc6\x6a\x2b\x8b\xc5\xcd\x0a\xec\x3e\xe8\xb3\x90\xee\xc5\x95\xd7\x16\x7e\xe5\xff\x70\x98\x31\xe5\x0e\x63\xce\x1f\x2e\x95\x8b\xf3\xda\xc8\x4c\x23\xba\x72\xe8\x1f\x5a\x82\xc1\xf5\x2f\xea\xb7\xa1\xa3\x9f\x9d\x5a\x5a\xdd\xda\x0e\x7f\x93\xc6\x77\x7f\x82\xa6\x7b\x65\xbd\x54\xac\x69\x75\x19\xd0\xff\x11\x7a\x60\xb5\xb8\x5d\x61\xdf\xa9\xfd\x57\xe8\xff\x01\x5d\xac\x15\x57\xcb\x3f\xfa\xa3\xe0\x09\xc6\x6a\xfc\x98\xe3\xc7\x95\xf5\xcd\xad\x3f\xfd\xe9\xf4\x59\xf8\xf2\x33\xf4\xaf\x57\x36\xca\x95\x7f\x7a\x55\xfd\x06\x63\x2d\xff\x00\xfd\x0d\xc6\xd5\x97\xf8\x1d\xe6\x64\x6e\xe5\x75\xe5\x73\x58\xde\xb3\x24\xff\x29\x3b\xc3\x15\x8c\xc0\x9c\x2a\x3b\xf2\x93\x5d\xc8\xcc\xb3\xf1\x07\xec\x81\x5b\x9d\xd9\xbb\xc9\x6e\xa8\x33\xec\x2e\xcc\xfc\x80\xa0\xda\xbf\x76\xdb\x36\x01\x8d\x9b\xba\x83\x75\x43\x6a\x90\x1c\x13\x60\x84\xbd\x3d\x22\x3c\x60\x24\x5b\xf9\xc3\x31\xb8\x76\xf4\xdc\xff\xcf\x3e\x88\xd1\x5e\x55\xbd\xa1\x7a\x98\x9b\x2d\x31\xf7\x77\xaf\x0a\x4d\x51\x62\x51\x3e\x10\xe9\x68\xe0\x81\xc4\x50\x67\xb3\x5f\xf3\x72\xcd\x15\x68\x09\xf8\x5d\x0d\xbc\xab\xa3\x17\x0a\xbe\x51\xde\x11\x19\xec\x8a\x74\xb9\xb4\x0e\xb4\x91\x81\xe1\x24\x1f\x8e\xf4\xf2\x38\xef\x1a\x1c\x18\x7a\x86\x0f\x0d\xdb\xc6\xfe\xc4\x49\x28\xf8\x9e\xe3\x89\xc0\x49\x1e\x68\x19\x1e\x4a\xb4\xd0\x60\x5e\x0e\x35\xc4\x95\x73\x33\xdb\x33\xca\xf5\xad\xeb\xbc\xdd\xed\x5a\xf2\xd4\x36\x75\x6b\x4e\x6f\xb6\xde\xe5\xba\x7c\xbc\xad\xc6\xe5\xf0\xbd\xe9\xae\xf3\x05\x5b\x9e\xd7\x7c\xda\x64\xc0\xe1\x74\x77\x7b\xbc\xee\x05\x97\x9b\x7b\x9c\x4b\xee\x86\x96\x4e\x8b\xeb\xbe\xdc\xda\x56\xe3\x56\x1b\xdf\x74\xd5\x71\x6f\x7b\x20\xeb\xf4\xba\x2e\xf8\x1d\x8e\x73\x0d\x35\x0b\x2e\x0f\x7f\xf9\xdc\xec\xec\xed\xd9\xd9\x6d\xea\xf5\x85\x9a\x83\x09\xad\x41\x6b\xce\x72\xe7\x58\xbd\xfb\x52\xbb\xcf\xe3\x5a\xac\xa9\x1b\x73\x6a\xe3\x21\x67\x83\x56\x97\xf0\xb6\x07\xbd\xbc\xce\x65\x72\x8f\xb7\x89\x98\xab\xce\xe5\xcf\x5a\x54\xaf\xdb\x6d\x52\x9d\xe9\x76\x50\x2f\x9b\x44\xab\x0a\x99\x7a\x8c\xff\x1b\xf3\xb2\x93\xac\x97\x79\x3e\x35\xf4\xf6\xa6\x3a\x55\x8d\x45\x9b\x10\xba\x2e\xbd\x23\x42\x11\x19\xee\x4f\x04\x9c\xb6\x3e\xfc\x98\x7e\x9e\x5b\xfa\x4f\x42\x2d\xaf\xb6\x84\xb8\x08\xbc\x1a\x10\xfc\x84\x25\x2c\xd3\x49\x53\xb1\x2c\x9f\x3e\x34\x1f\xa6\x3c\x82\x29\xaf\x7b\x7b\x7b\x37\xd5\x3f\x56\xeb\x91\xd7\x30\xf2\x7a\xbc\x56\x53\xcd\xbc\xc6\xb9\x16\xe2\x49\xce\xfd\x1a\xa5\x52\xef\x88\x2b\x49\x47\x48\x69\xf1\xbb\x5a\x02\xca\xd7\xbf\xf9\xa3\xbb\x8e\xf7\xbf\x7c\x8f\x77\x18\xa3\xfe\x2f\xe6\xdf\xc8\x7e\xb0\x34\xae\x8c\xad\xbc\x7f\xef\xbd\xca\x88\x9a\xf9\xa2\x99\xff\xd6\xe2\x07\xca\xdd\xbf\xf9\x7d\xed\xbd\xdd\x3f\x38\xd1\xd3\xfc\x45\x26\x79\xf3\xce\xb7\xdf\x5f\x1b\x75\xa4\x16\xee\x5e\x7e\x63\xfe\x8b\xe6\xfd\x7a\x6a\x52\xeb\x10\x8d\x6e\xcc\x8b\x32\xa2\x7a\xea\xf4\x6b\x7a\x18\x15\x33\x90\x74\xb6\x24\x42\x4a\x22\xa9\xf4\x27\x42\x4e\x15\x4e\x44\x92\xa8\x02\xf5\xd8\x4c\x7a\xb7\x35\x3d\xe3\xa8\x3b\x16\x8a\x8c\x86\x9d\x11\xe3\xd2\xc5\x8b\x7d\x1d\xae\x8e\x91\xee\x76\xbf\x47\xfb\xe4\x2d\xf9\xb6\x63\xfb\xb3\xdb\xa9\xf4\x95\x2b\xe9\xd0\x48\x6a\x68\xa4\xa3\x4d\x69\x0d\xb5\xe2\x2f\x10\x19\x18\x4d\x8e\xf1\x9f\xe4\xde\x02\x47\x79\x93\x69\xb4\x6e\x47\x2f\x4e\x8c\x46\x96\x60\xe7\x70\x32\x5c\x67\xaf\xb0\xc6\xf1\x86\xaf\xe5\x67\xa7\xd2\xc9\xb3\x83\xc2\xef\x52\x34\x04\x42\x73\x51\x2a\x06\xe0\x06\x1f\x4e\x0c\x6b\xcd\x7e\x6e\xb9\xd8\x05\x17\x61\x54\x92\x9c\xaa\x38\x11\x72\xb4\x50\xa8\x22\x03\x43\x89\x00\x40\x9c\x27\x95\x80\x93\xf2\x16\xe9\x1a\x1a\x1c\xe8\x0a\xf4\x27\x92\xbc\x25\xd1\x75\x40\x99\xbe\x31\x3a\x1d\x1b\xe7\x19\x47\x4f\x2a\x1c\xe9\x54\x95\xaf\xd3\xc2\x26\xb2\xdc\x51\xe7\x13\x58\x99\x76\x2a\x7e\x21\x3b\x79\xfc\xb4\xcf\xa5\x8f\x44\x84\xaf\x81\x7f\xf5\x03\x2a\xce\xdb\xb3\xfc\x77\x4c\xff\x3f\x79\x9d\xa7\x93\xf1\xe9\xb3\x37\x62\x6a\x67\x67\x78\xa2\xdb\x91\x99\xb2\xfb\x5f\x56\x27\x0c\xe3\xaf\x02\x6d\xbc\xbe\xd9\x77\x65\xf7\xc5\xd4\x95\x2b\x29\x44\x62\x64\x20\x12\x68\x6d\x6f\x53\x02\xbe\x36\x8f\x82\x58\x8c\xa4\xda\x95\xdf\xb3\x0a\x7e\xf7\x97\xf9\xb7\x94\xd7\xff\x6c\x5b\x7b\xe7\xef\xa3\x71\x3e\xa1\x3e\x7b\xc5\xd7\x5c\xdf\xda\xca\xed\x6e\x7b\xef\x7f\xa8\xbe\xa3\x0a\xd6\xc2\x42\xc8\x55\xe8\x78\xbd\x13\xb9\x0a\x0f\xf6\x37\xdb\xe9\x6a\x1c\x18\xea\x0f\x27\x02\x27\xb8\x3e\x18\x6e\xe4\xae\xc1\x30\xbe\xfc\x57\x73\xa3\x3d\xbb\x95\xee\xb1\xb1\x6e\x7e\xa7\x67\x74\x6e\x77\x4d\x15\x3f\xd8\x4d\xf2\xbf\x98\x9f\x27\x9b\xf2\x79\xcf\xe8\x68\xcf\xdd\xbb\x5f\x4d\xf0\xc9\xbf\xdc\xbe\xbb\xcd\xec\x3d\xa2\x7c\xae\xe4\x58\x2d\x66\xd2\xb1\x47\xda\x5b\x7d\x75\x0e\x86\x3d\x82\x43\xc1\x9a\x0a\x13\x0d\x9a\x6d\xd8\xb4\x34\x1e\xb2\x2b\x3b\x81\xf6\x90\xff\xab\x3f\xf1\x87\xda\x03\xf4\x53\x72\xa4\x3f\xb4\xf1\x3b\xa1\xee\x10\xfe\xe6\x2d\xb1\xfb\xa5\x25\xcd\xfb\x62\xef\xbf\xd4\x63\x6a\x2d\xe6\xd4\x3e\x6e\xab\xe1\x98\xcf\xdc\x73\x68\xcc\xec\x0f\x1e\xec\x4e\x34\x74\x40\xb5\x34\x63\x1f\xaa\xc7\x44\xe0\x81\xb5\x9f\x1e\x98\x3b\xeb\x81\xb5\xad\x1e\xec\xef\xbe\x9f\x07\x60\x6d\xfe\xf9\x81\x95\xe8\xb4\x44\x9a\xef\x97\xca\x97\xca\x6f\xb3\x53\x98\x2f\xe0\xe0\x54\xf7\x38\x3c\xb1\xd1\x5c\xd4\x44\x06\x9e\xe1\x5d\xd4\x0c\xe1\x50\x1c\xa6\x86\x8e\x41\xec\xbb\x2f\xbd\x97\x7c\x86\xef\xde\x3d\x34\x97\x7c\x24\x7d\x0f\x75\xaf\xf7\xde\x3d\x6f\x25\x40\xe0\xa3\x8f\xbc\x4f\x12\xbd\x71\x22\x98\xf7\x1a\x7e\x3f\x5e\xfa\xc3\xfe\x57\xbc\x63\xff\xc9\x6a\xd5\x07\xe4\xd2\xdf\xdd\xfa\x30\x6b\xc9\x0d\x71\xb0\x33\x70\xa1\x53\xee\x99\xed\xb3\x75\xc7\x3a\x7a\xe1\xfd\xae\xa3\xef\xd0\x2d\x6b\x7d\x3c\x34\x92\x8a\xb7\x0e\x15\x6f\x12\xea\xb7\x2c\x49\x6c\xf5\x1d\xca\xaa\x6d\x6f\xb4\xd9\xdf\x62\xbf\xe0\xdd\x7c\x89\xef\x2a\x09\x65\x4d\xf9\x8e\xf2\x33\x6b\x0e\xe6\x61\xcb\x4c\xdb\xbf\x71\xf0\xce\xb2\x89\xb6\xa3\xb6\x62\x3f\x75\x8c\xfd\xf3\xc1\xbc\x83\x6c\xff\xa6\xe7\xf0\x73\xd0\xc6\x0a\x73\xb1\xf3\x36\x56\x61\x9f\xb0\xb1\x03\xf8\x92\x8d\x9d\xa8\xaf\x59\x1b\x6b\xb0\xbf\x62\x63\x0f\x8b\xb2\x45\x1b\xd7\xb2\x26\xf6\x01\xbd\x2d\x38\x6a\xa0\xdd\x64\x1f\xd9\x98\x33\x1f\xf7\xda\x58\x61\x0d\xfc\xa4\x8d\x55\xd8\x63\x36\x76\x00\x9f\xb7\xb1\x93\x05\xf8\x65\x1b\x6b\xb0\x97\x6c\xec\x61\xd7\xf9\xa6\x8d\x6b\x59\x84\xff\x75\x7a\xbd\xf2\xda\xc6\xf2\xe2\xd2\x96\xe8\x4e\x9f\x16\x89\xbe\x33\x83\x62\xee\x35\xb1\x0e\xd3\xf2\x5a\x71\x45\x14\x6f\x6d\x2d\xad\x6f\x6c\x8a\x71\xb1\xb0\xbe\xb6\x55\x5e\x59\x59\x8f\x97\xd6\x57\xf7\xf1\x4c\x79\xf1\xd6\x4a\x71\x63\x5f\xdd\x97\xd7\xcb\x1b\x9b\xcb\xeb\x6b\xe2\x4c\xbc\x6f\xdf\x34\x55\x5e\x2b\x6f\x14\xb7\xca\xf3\x34\xfa\xe6\xed\xc5\xc4\xd6\xd6\x82\x58\xd8\x58\x5f\x15\x93\x36\x43\x54\x36\xd6\x6f\x96\x4b\x5b\xf1\xa5\xad\xad\xca\x68\x6f\xef\xe1\xf9\x58\x9a\xad\xb3\x0a\x7b\x8d\x6d\x20\x4d\x8b\x78\x11\xd8\x62\x02\xc7\x77\x9a\x9d\x86\x4c\xb0\x3e\x76\x06\x89\x10\x6c\x0e\x0c\x01\xa6\xc5\x5a\x66\x6b\xac\xc8\x56\x60\x29\xb2\x5b\x78\x62\xc9\xec\xd9\x84\x3e\x8e\xdf\x02\xb4\x35\x58\xcb\x60\xac\x00\xc7\x59\x09\xed\xea\x13\xf6\x19\xa0\x45\x3c\xbf\x82\x51\x36\x9e\xe8\x7d\x5c\xbf\x0e\x44\x73\x2c\x9b\x76\x01\xbf\xe2\xf0\xee\x71\xd6\x14\xd0\x9a\xc9\x2c\x9a\xd6\xf9\x03\xdf\x37\xd9\x6d\xcc\x96\x80\x75\x0b\x4f\x91\x97\x1b\xa6\x57\x82\x4d\x3e\x36\x86\x40\x3c\xa8\xef\x26\x2c\x25\xd8\xe3\x66\x54\xb6\x60\x1d\xc5\x35\xdf\xfb\xd4\xf5\xd9\x15\x6e\xd5\xdd\xd1\x1f\xd8\xb9\xc2\x55\xee\xe0\x4e\xae\x71\x17\x77\xf3\x1a\xee\x51\x4b\xeb\x8b\x6e\xe4\x63\xb9\xb2\xb9\xbc\xa9\x6d\x96\x8b\x1b\xa5\x25\xc7\xad\xcd\xf2\x86\x93\x9a\x4d\x6d\x65\x7d\x71\xfd\xd6\x96\x63\xb5\xbc\x76\xcb\x51\x59\xb9\xb5\xa9\x95\x8a\x6b\xa5\xf2\x8a\xb5\x4f\x38\xde\x6e\xbd\x87\xa7\x90\xcc\x10\x92\xbd\x90\xcb\xe4\x85\x98\xfe\x8c\x35\x5c\x9d\x96\xda\xb5\x1b\x39\x39\x10\x94\xdd\xf9\xc2\x82\xd8\x79\x21\x27\x95\xce\xe2\xf7\xdc\xd8\x26\xa5\x92\x3e\x17\x0c\x87\x25\xcb\x4b\x96\xd6\x27\xee\x63\xbc\x74\x21\x15\x93\xdc\x90\xa2\xb0\x10\x93\x8a\x21\xe6\x85\xfc\x7e\x56\x3a\x22\x37\xee\x77\x73\x4f\x3a\x53\xca\xcc\xbc\x98\x0b\xeb\xe1\xe0\x4e\x4e\xc8\x6c\x36\x17\x96\xe3\xf9\xa0\x90\x23\x84\x46\xf2\x79\x51\xb5\x48\xc5\x79\xd9\x0d\x93\xad\x09\xd9\x47\xfd\x7d\xc4\xfc\x7e\x36\x27\xe0\xc4\x4e\x51\x48\x4f\x36\x57\x80\x45\x50\x9f\x87\xd0\x10\xa1\xa1\x42\xb0\x90\xcf\xe7\x83\x92\x47\xf3\x79\x5d\xb2\x6c\xae\x9c\xcf\xc7\xa4\x6a\x08\x8c\xe3\xe8\x2c\xc2\x21\x67\x3a\x9b\x93\x4e\x3d\x25\x35\x3d\x05\xf7\xf3\x92\x17\x62\xd2\x61\xe8\xf0\x4b\xcc\x57\x9d\x73\x29\x41\x3d\xd6\xe4\xd4\x4a\x56\xc8\x94\xa4\xda\x13\x86\x3d\x2d\x76\xc4\x0e\xc6\xae\xf6\x39\x3b\xb1\xac\xab\xb9\x42\x36\x58\x9c\xc9\xe7\xf4\x3c\x7a\xc7\xaf\xe5\xd0\x15\xa4\x45\xd9\x33\xc7\xa4\xd3\x90\xae\x74\xf4\x3e\x52\x6b\x86\x46\x83\xaa\xa7\x74\x84\x58\x4f\x15\xa5\x32\xb7\x20\x79\x09\xf3\x4b\x67\x4f\x4c\xba\x0c\x41\x4e\xd6\xa6\x4b\x9f\x39\xd8\x9c\xa0\x11\xe4\x78\x21\x4f\x94\xc2\x84\xe9\xa4\xdb\xb8\xef\xaa\x65\xe9\x4c\xaa\x27\x7c\x10\xec\x1a\xe3\xd1\xe0\x7b\xac\x51\x78\x14\x2e\xa4\xb1\xe2\x82\xc8\xec\xe8\x45\x4a\x84\x19\x29\x16\xa4\x68\x4a\x11\x84\x93\xfb\x5e\x4a\xb5\x53\x2f\x4e\x58\x53\xd4\x3e\xe5\x71\x79\x0a\x4f\xb1\xe0\xc3\xa5\x1d\x7e\xa8\xce\x30\x17\x74\xbf\xd6\xa3\x66\x72\xe1\xa0\x1e\xce\xf7\x84\x63\xb2\xde\xa8\x2a\x4a\x46\xce\x17\x27\x62\xb2\xc1\x00\x51\x08\x59\x97\xbe\x48\x8f\x03\xe8\xa9\xbc\xac\x27\x6d\x06\x5a\x3d\xb4\x98\xf4\x62\x18\x9f\x19\x12\x81\x08\x94\x30\xaf\x6c\x48\x17\xc4\x4e\x41\xc8\x06\x04\x2d\x26\x7d\xc6\xf4\x6c\xae\xea\x98\x9f\xc8\x9f\x92\xf5\x65\x7d\x3b\x26\x1b\x8d\xe9\xab\xb9\xe9\x6b\x96\x31\x18\x86\xbd\xc9\xb4\x1f\x33\xaa\xcc\x9b\x7e\x21\x57\xf5\x7a\xd3\x92\x17\x53\xd2\x1b\xa5\x22\x45\xe9\xa6\xaa\x75\xd4\xd4\xa3\x91\x3c\x80\x4c\xa8\x9d\xd9\x5c\x95\x82\x87\xd5\xa6\x76\x90\x5e\x9a\xb6\x27\xac\xe3\xb1\x7d\x1c\xb4\xfa\xe9\x11\xd4\x3e\x59\xf2\x58\xc9\x14\xfc\x9f\x82\xf5\xd1\x54\x3d\x25\x81\x55\xc6\x9a\x74\x44\x0b\xd5\x94\xbc\xcf\x39\x37\x73\xd5\x64\xb0\x2a\x53\x32\xb3\x39\xe9\xd5\x53\x22\x23\x6b\x51\x94\x1e\xc4\xb7\x90\x12\x05\x4c\xff\x5d\x9f\x8f\xe3\x7f\xfe\x54\x6a\xa7\x50\x3d\xa6\x45\xe5\x46\x34\xd8\x81\x30\xf9\xb1\xb6\xa6\x68\x4c\x36\x1b\x55\x4e\x32\x80\x38\x93\x6c\x31\xf0\xfe\x0c\xd9\x6a\x54\x1d\x24\x8f\x1b\x55\x27\xc9\x36\xa3\xaa\x91\x0c\x1a\x55\x17\xc9\x76\xa3\xea\x26\x79\xc2\xa8\xd6\x90\x0c\x19\x4c\xd6\x47\x7f\x0d\x47\x4e\xc2\x91\x10\x06\x10\x70\x84\x64\x18\x8e\x90\xec\x80\x23\x24\x75\x38\x42\xf2\x14\x1c\x21\xd9\x09\x47\x48\x46\xe0\x08\xc9\x2e\x38\x42\xb2\x1b\x8e\x90\x3c\x6d\x88\x31\xb3\x9e\x7a\x0c\x4c\xeb\x2b\x88\x34\x92\x50\x48\x9b\x31\xc7\x1e\x39\x4d\x45\x15\x35\x64\x4f\x54\xf6\x60\xbb\x18\xa8\xd4\x29\xf1\x94\x70\xeb\xc5\x11\x9d\xce\xaa\xff\x91\x81\x7a\x89\xc9\xd8\x41\x0e\x78\x40\x1a\x3d\x92\x37\xf7\x99\x8b\x8b\x1f\x8e\xca\xa3\x5d\xbd\x86\x18\x34\xfd\xec\x03\x87\x67\x9e\x1c\x1c\xdb\xe7\xc8\x49\xc9\xce\x02\x9f\x98\x07\xed\x44\x52\x1f\xa9\xf6\xf2\x66\xac\xe4\x0c\xd6\x0d\x47\x8f\xf6\x13\x55\x5b\x1c\x89\xc9\x84\x11\x6f\x19\x8b\xc9\xfe\xff\x8d\x8a\x0a\x2b\x81\x3e\x80\x54\xb0\x40\xa7\x88\x8b\x29\xda\x99\x08\xe1\x73\x3b\x3b\x53\xfa\x14\xb6\x72\x0e\x67\x36\xce\x3c\x6c\xd7\x7e\x8e\xb7\x5a\xcc\x3f\x88\x23\x24\x80\xea\xc7\x9f\x49\x91\x35\xe9\x68\x79\x27\xae\x0b\x31\xb6\x83\xb1\x86\x1e\x76\x8b\xb8\x35\x86\x74\x60\x4c\xb0\x84\x2c\xd0\x66\x1e\xbf\x9a\xfb\x58\x11\xaa\x08\x7e\xac\x44\xd4\xb6\x7c\x8a\x0e\x38\x37\x8e\x4a\xdd\x64\xeb\x93\xd8\x5a\xe9\xc7\xf7\x49\x81\x0e\x19\xeb\x24\x57\xd2\x85\x79\x5d\xaa\xe9\xe2\x3c\xba\x95\x74\x31\x08\x5c\xa0\x03\xe6\xf1\x67\x8a\x70\x09\xa7\xae\x3e\x89\xdc\xe9\x98\x61\x12\xeb\x82\x30\x67\xc1\x78\x47\x4c\xa2\x5b\x47\x99\x03\xbb\x17\xb1\x77\xa2\x90\x9c\x4f\x8c\x8a\x11\x69\x45\x9d\xa6\x13\x68\xb3\xd6\x11\xf6\x70\x2e\xa4\x7c\x98\x62\x20\x60\x71\x46\xec\x18\xe8\x63\x08\xcd\x88\x69\x96\x6e\x6c\x1a\x21\x26\xf5\x29\x9a\x8c\xb2\x75\xd6\x0c\x19\x2d\xc0\x8e\x28\x9b\xcd\xc5\xc5\x18\x2e\x3e\xf2\xd8\x36\x0a\xf2\x65\x3f\xe4\x5a\x27\xb4\xe7\x0e\x5f\xad\x56\xa2\x8e\xaa\x5c\x3b\x33\x3a\x95\xef\xa8\xed\x41\x7a\x3f\x35\x05\xba\x7b\x1f\x5f\xe2\x7e\x2a\xcf\x19\xba\x88\x53\xd4\x26\x71\xea\x8e\xe5\xe3\xd5\x28\xf7\x63\xe3\x8d\x1d\x98\xb3\x87\xcd\xe7\x1f\x65\x1f\xc9\x49\x1a\x72\x30\x7a\xe4\xa0\xcf\x18\x72\x28\xba\x83\x89\xa9\x58\xe0\xed\x93\x1c\xa4\x25\x2e\xa3\xa0\x8e\x1f\x54\xd8\x7e\x74\xa9\xb8\x74\x94\x7a\x1c\x9b\xc4\x1a\xee\x59\x1c\x16\x38\xa0\x7f\x8d\x52\x9c\xfa\xbf\xaa\x3e\x72\x9f\xce\x95\x31\x1d\x47\xc7\xa1\x7c\x87\xf3\xb6\x8f\x29\x0a\xc6\xfe\xfa\xd3\xb4\xfe\xb0\x6e\x07\xc0\x5e\xc7\xc1\x92\x27\xb0\xe4\x66\x6b\x73\xe2\xea\xc6\x3e\x6c\x8a\xcb\x33\xd8\x8b\x99\xa7\xd8\x27\x71\xd6\x72\x7f\x93\x4c\x00\x4f\x19\x72\x00\xe2\x02\x45\x2d\x83\xb8\x8a\x49\xdc\x53\xfb\x71\x7a\xce\xa0\x72\x94\x17\x00\x2f\x1a\xf7\x19\x7b\x16\x60\x1a\x80\x13\xb8\x64\xdc\xe7\xa6\xe5\x32\x80\x69\xb9\x42\x9c\x14\xc0\xf3\xc4\x21\x90\x25\x0e\x81\xab\xc4\x21\x30\x43\x9c\x24\xc0\x35\xe2\x10\x98\x25\x0e\x81\x17\x88\x43\xe0\x3a\x71\xc6\x01\x7e\x83\x38\x04\x72\xc4\x21\x90\x27\x0e\x81\x1b\xc4\x49\x03\xbc\x48\x1c\x02\x2f\x11\x87\xc0\xd7\x88\x43\xe0\x65\xe2\x3c\x03\xf0\x0a\x71\x08\x14\x88\x43\xa0\x48\x1c\x02\x73\x86\x1c\x3e\x08\x73\x89\x14\x79\x0e\x68\xde\x44\x63\x40\x65\xb3\x9e\xa0\x9c\x87\xb2\x60\xc8\x91\x03\xf6\x22\x29\x26\x7b\xc9\x44\xc4\x5e\x36\x11\x51\x6f\x1a\xf2\xec\x01\xf5\x55\x52\x4c\xea\x8a\x89\x88\xba\x6a\x22\xa2\xae\x19\x72\xf4\x80\xba\x4e\x8a\x49\xad\x98\x88\xa8\xbf\x69\x22\xa2\x6e\x18\x1f\xd7\x38\x94\xfd\x37\xa3\x54\x54\xba\xcb\x52\x3d\x95\xdd\xa6\xfb\x24\xc6\xf0\x92\xfd\xc3\x19\xbc\x80\xf0\xf7\x71\x28\x5b\x7b\xbf\x52\x65\xce\x14\x5e\x18\x7a\x2c\xe9\x7e\x44\x7e\x0f\x77\x47\xcd\x61\xa4\xb2\x89\xea\x29\xfe\xee\x55\xd4\xe9\xbb\xb9\xaa\x3a\x3f\x51\x8d\x90\xf6\xe7\xee\xb7\xf1\xbf\xe4\xf8\xbb\x25\xbc\x31\x81\x82\x77\xe2\x7c\x95\xd5\xf5\x7c\xc6\xf7\xbe\x21\x1d\xbf\x8b\xdb\x61\x82\xfd\x37\x88\xf0\x61\x56\x54\x18\x00\x00" - -func font_fontello_ttf_gz_bytes() ([]byte, error) { - return bindata_read( - _font_fontello_ttf_gz, - "font/fontello.ttf.gz", - ) -} - -func font_fontello_ttf_gz() (*asset, error) { - bytes, err := font_fontello_ttf_gz_bytes() - if err != nil { - return nil, err - } - - info := bindata_file_info{name: "font/fontello.ttf.gz", size: 3490, mode: os.FileMode(438), modTime: time.Unix(1432348676, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _font_fontello_woff_gz = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x0b\x65\x56\x67\x34\x9c\x5b\xd4\x9e\x31\x8c\x36\xcc\xa8\x21\x46\x8c\x76\x75\x46\x2f\x41\x88\x16\x65\x10\xbd\x07\x63\xb4\x21\x3a\x89\x9a\x51\x27\x88\x16\xbd\x64\x08\x41\x24\x88\x68\x41\xb4\xab\xb7\x88\x88\x96\x10\x9d\x11\x25\x48\x82\x88\xf2\x4d\xee\xbd\xdf\x8f\x6f\x7d\x67\xad\xe7\x3d\x67\x3f\xfb\xd9\x7b\xaf\xf5\xbe\xef\x5a\xe7\x09\x31\xd2\xd6\x06\x00\x01\xa4\x45\x9f\x0b\xa0\xff\xb3\xb3\x99\xfd\x1b\xff\xff\x65\x64\x2a\x21\x05\x00\x00\x35\x49\xc7\x3f\xb0\x50\x15\xbc\xf5\x1d\xed\xed\xe4\x4b\xe2\xf0\xa4\x58\x89\xb4\xeb\xbd\x67\x67\x6f\x46\x07\x07\x22\x48\xe7\x5e\x12\x47\xf3\x1f\x00\xae\xbe\x6e\xde\x24\xee\x3d\x00\x40\x91\x09\x00\xd0\xfa\xe2\xd3\xd2\xac\xdd\x9c\x02\x48\xb5\x94\x2e\xa4\x34\xd5\x7f\x80\xb9\x79\xdd\x77\x25\x71\x5e\x00\x00\xf9\x2d\x92\x76\xf0\x88\xb9\x50\xde\x1d\xe3\x44\xd2\xd0\x36\x90\xf2\x32\x24\xc8\x81\x15\x4c\x18\xdc\x49\x24\x89\x23\x92\x62\xd2\x2c\x00\x1f\xe5\x22\xe8\xa9\xbb\x77\xe0\x3d\x00\x00\xf2\xa7\x0f\x37\x09\x82\xdc\xa4\x49\x5e\x3e\x68\x92\x0e\x22\x4a\x8a\x59\xff\x80\x9a\x8d\x52\xd4\xdb\xe9\x1e\x69\x2e\x44\xf3\xbf\x5a\x04\xa0\x9c\x76\xfb\xae\x93\x37\x86\xc4\x91\xe6\x00\x43\x00\x00\xb2\xb1\xd1\x22\x0e\x4e\x5f\x9f\x80\x40\x00\x80\x6e\x9e\xa4\x31\x25\xc1\xa7\x6a\x49\x5f\xd1\xd7\x1f\x43\xaa\xa5\x47\x92\x62\x92\x1e\x10\xb6\x80\x05\xc5\xdd\x2b\x44\x3b\xba\xa4\x38\x15\x76\x75\x0d\x77\x75\x9b\xf5\x35\x24\xe0\x70\x25\x94\x37\xa5\x55\x1d\x91\x2e\x2e\xce\x8e\x8e\xce\x8e\x18\xd7\x2e\x1a\xb2\x0f\x76\xa6\x6c\x70\x07\xe4\xdb\x25\x47\xfa\x53\x42\x1f\xac\x0f\xde\x8b\xa4\x13\x1c\xa5\xca\x00\x01\x16\x4f\x69\xf3\xfe\xf4\x70\x74\x74\x7d\xe0\xc8\x0e\xd6\x06\xc3\x7c\x81\x87\x6c\xdd\xe1\xac\x60\x3a\xc4\x18\xb8\x8c\x9d\x3d\x97\x8d\xcd\xc1\xf7\xec\x12\x6a\xb2\x1f\x0d\xd4\xd4\x47\xde\x9c\x02\x01\x79\x39\x7a\xf0\x94\x00\xaf\x5a\x70\xd3\xff\xfd\x46\xf7\x0a\xab\x2d\x3c\x02\x98\x74\x60\x45\x53\x4e\x23\x72\xaa\xd1\x50\x46\x39\x9c\x75\xbf\x7f\x72\xb0\x45\xee\x08\x15\xac\x7f\x47\x8f\x75\x09\x7e\x98\xb5\x73\x33\xc5\x5e\x3f\x78\x2f\xc9\xe8\x0c\x7c\x9e\xef\x90\x6e\x96\xee\x73\xd6\xf0\xf6\x1a\xe7\xac\xa3\x80\xb9\x99\xa0\xde\x79\xf9\xf1\xae\xc1\xf1\xf6\x13\x87\xc7\xef\x33\x7a\x1d\xac\x52\xcb\xe6\xc3\x85\xca\x9b\xe4\x3c\x5c\x36\x75\x6f\xc9\x7b\xd9\xa4\xac\x68\xcc\xcd\xd1\x0a\x99\x1a\x5c\x88\xe3\xa3\xdd\x1b\x3f\x76\xec\x2a\xf0\xf1\x30\xe2\xaa\x82\xe2\xf8\xa3\x67\x8f\x07\x3f\xf0\xad\x6a\xa4\x4a\xd9\x34\xf1\xb7\x7b\x9a\xdc\xdd\xd2\x0d\x99\xbb\x0a\xfd\x5a\x7d\x7a\x34\xf9\xfe\x76\xca\x02\x35\xbf\x6c\x41\x89\xc6\x76\xba\xd8\xf3\xbf\x2b\x19\xb5\xa4\x76\xd3\x33\xe4\xc4\x7a\xa6\xee\xe8\xda\x2c\x6f\x8a\x8c\x86\x4f\x41\xf8\xa3\x89\x7c\x19\xfd\x05\x4e\x90\xd4\x35\xb7\xd5\x64\x0b\xf6\xea\xfe\x60\xb8\x56\x3a\x2a\x9b\x43\x2b\x51\x53\x5a\x19\xcf\x93\xfa\xda\xc6\x99\x60\x27\xa9\xae\xf6\xab\x98\xdd\xc4\xe1\x97\xcc\xd3\xf0\x58\xae\x74\x96\xb0\xcc\x49\x1a\xbf\xa1\xe0\xfc\xc5\x63\xfe\x1b\x5b\x9c\xef\x3a\xf9\x56\x42\x93\x5e\xf3\x53\x5e\xa8\x05\xbb\x50\x86\x55\x88\xfc\xe2\xf9\xf0\x89\x66\xb5\xbc\xc8\x4b\xa7\x24\x71\x3f\x30\x42\xa0\x97\xb7\xe0\xf1\x57\xc2\xce\x6d\x87\x49\xf7\xa5\x60\xad\x72\x81\x31\xaa\xec\x61\xcb\x34\xab\x5f\xd4\x98\x23\xe8\x90\xe7\x72\xf8\x70\x8e\xf2\xd5\xa9\x8c\x98\x42\x2a\x1b\x89\x00\xe7\x3b\x87\xf4\x0d\xd7\x74\x0c\x1e\x62\xff\x1a\x8c\xde\x4b\x31\xc4\x17\xef\xe5\x14\x96\xcc\xa2\x4f\xdf\x9c\xac\xb6\xdb\x8b\x5e\xe1\x26\x1f\x54\xc8\xfe\x99\xa2\xf7\x06\xa6\x2d\xe4\x54\x9f\xcf\xe7\x4d\xae\x88\xcf\x78\xad\x95\xf5\x31\x54\xc7\xa0\xf0\x50\x49\x6c\x45\xcc\xa9\xd3\x70\x97\xa8\xef\xd6\xa0\x5b\x79\x5d\xf2\x49\x75\x42\x4a\x75\x61\xe5\xda\x3d\x99\xe7\x93\x06\xe5\x86\xbb\x65\x1b\x13\x99\xe0\xdb\x7a\x4a\x4c\xca\x1b\x33\xc0\x4c\xae\x09\xbe\xda\xa6\xba\xfc\xde\xe1\x52\x0f\x2f\x69\x34\x5f\xba\x71\x71\x5c\x80\x87\x30\x1e\x23\x90\x2d\x43\x31\xa1\x9c\x3f\x51\xd0\xe6\x94\x8f\x9d\x79\xaa\x95\xaf\x6c\x3c\xae\x12\x6a\xe4\x73\x37\xae\xe0\xba\x4a\xc5\x6e\xd7\x0d\xec\x99\x5b\x90\x70\x79\x4c\x3b\xb2\xe8\x09\xfd\xa0\x5e\x78\x7e\x70\x8b\xee\x44\x6b\x64\x68\x7c\xd4\x5f\x07\x1a\xd3\x64\xc2\xe9\x62\x72\x3d\x99\x7d\x1a\x4d\x91\x94\xeb\xeb\x68\xfd\x94\xbf\xb1\x20\xaf\xe3\x27\xdf\x45\x88\x11\x47\x9a\x83\x65\xb8\x13\x8e\xfd\x6b\x12\x53\x42\x14\x06\x71\xb9\xe6\xc6\xb4\x0b\x0d\xd3\x8d\xa2\x23\x1f\x3d\x2d\x92\xcc\x5c\xbe\xb6\x71\xa3\x44\xee\x4c\x7b\x90\xa1\x14\xe9\x23\xd0\x77\xfa\x15\x2e\x6a\xf3\xd8\xf5\x0d\xa8\x17\xbf\xf5\x6e\xcd\x31\xe4\x3c\x69\x39\xe2\x1f\x94\x49\x98\x77\xb5\x4f\xdd\x08\xf2\xac\xb3\x7f\xf0\xce\x6b\x7c\x4b\x66\xe4\x28\xa2\x68\x63\x36\xb2\x78\x52\xf9\xf3\x77\x25\x4e\x27\xec\x76\x60\xe6\x6e\x82\x92\xd8\xab\xf3\x5b\x15\x68\x2f\x09\x77\xf5\xc7\x7b\xd7\xc9\xfd\x19\x70\x76\x5d\x60\x46\xdc\xab\x20\x18\xd5\x67\x7d\xaa\xd8\xea\x9b\x08\xaf\x2b\x0c\x54\x9f\x79\xc8\x9c\xda\x62\xd5\x66\x23\x93\xd5\x66\xc5\x79\x61\x4d\x39\x8d\x2f\xf3\x23\x85\x3d\xe0\xd7\x99\x46\x00\x5a\x78\x50\xa9\xe2\xde\x20\xe6\xae\xb0\xa5\xe9\xd0\x33\xc6\x9a\x24\xed\x0a\xb9\x35\x21\xff\x17\x65\x4f\xef\x59\x9c\x8b\x80\xce\x57\xd2\xe5\x5f\xe2\x1a\xd5\x5a\x35\xa7\xcf\x12\x75\x6b\xc2\xcd\xb2\x56\x53\x6b\xdc\xef\x4f\xf6\xb6\x90\xa5\x98\x47\x85\x05\xd8\x11\x98\xa0\x98\x4e\xab\x13\xd3\xfd\xce\x4f\xf9\x55\x65\x96\x2f\xef\xbb\xf8\xb3\xdc\xe7\x7d\xff\x78\x55\x73\xe6\x2f\x96\xd4\x9a\xad\xc3\x96\x2a\x9d\x99\xcb\xa4\x44\x7a\x2c\x2e\x12\xf4\x0c\x46\xab\x65\x9d\x4d\xd7\x91\x97\xb6\x7f\xbb\x62\xd2\x98\xce\x6e\x1d\x26\xcd\x21\x0d\x9d\xf9\xd9\x8a\x19\x1b\x5f\x3e\x2b\x60\xe3\xa6\x25\x46\x9e\xc9\x33\x5f\xa5\x9d\x8f\x31\xb4\xd6\xb5\xde\x75\xac\x9d\x9a\x49\xc5\xb4\x34\x53\xae\xbf\x12\xb0\xca\x70\xee\x18\xdd\xb6\x5d\x4e\x4a\x1e\xd5\xfb\xad\xe5\x2a\x14\xa6\x7a\x78\xbf\x8b\x05\x29\x9c\xe5\xf4\x82\xce\xae\x7a\x69\x2c\x8c\xf1\x7b\xda\x16\xea\xd0\x00\xd6\xcc\x82\x89\x29\x7b\x34\x90\x87\xa8\xc3\xa1\xaf\x21\x7d\x3a\x1e\x23\xf8\x0c\xec\x1b\x71\x9f\x84\x0a\x5f\xe1\xde\x3a\x8e\x0a\xcd\x7e\x8b\xd5\x30\xf3\xc9\x5c\xf7\x0d\x2b\x89\xb8\xf6\x28\x33\x0a\x6b\xb9\x33\xc8\xce\x82\x82\x9d\x78\x1f\x69\xcf\x6e\xd7\x1b\x1f\xda\xbe\xc4\xc5\x0a\x74\x7e\x9c\x51\x33\xe7\x46\xf5\xbd\x79\xfe\x40\x9f\x77\x3d\xde\x73\xdf\xc9\xae\xfa\xb3\xb6\x94\x61\x71\x6d\xe5\x2c\xdd\xc8\xeb\x44\x28\x97\xce\x7c\x88\x5e\x0a\x06\xf1\xeb\x16\xc3\x0b\x1d\x9d\x1b\xd5\xed\x37\x8b\x3e\xb6\x9c\x0f\x0b\xde\x5d\xbc\x7e\x4e\x15\xad\xee\xe1\x7c\x71\xd4\x91\xb7\x52\x9c\x19\xd2\x98\x81\xb1\xf0\x06\x99\x36\x5f\xcd\x32\x9d\xc9\xef\xe9\x7b\x41\xbf\x30\x56\xba\x17\x36\x30\x27\xe0\x3f\x2d\xb3\x10\x68\x34\xff\xa3\xa3\xdc\xbc\x39\x26\xa6\xc5\x1a\xb6\xfb\x19\x9e\xf9\xcc\x40\xbc\x72\xbb\x87\x9e\xa3\x72\x64\xec\xd9\xfb\xaf\x18\xbb\x8c\x2f\xc1\x50\xa4\x28\xb2\x78\xb1\x84\x85\xe3\xd2\xf2\xd8\xef\x44\xd9\xb2\x8a\xa6\x74\xf5\x56\x7b\x51\x25\x57\xe9\xb8\x33\xe4\x10\xaa\x10\xa5\xf3\x93\x82\xb8\x29\x69\xd0\x12\x9f\xb9\x19\x96\xc3\x44\xb8\x3b\xdf\x33\x27\x65\xdf\x67\xff\x92\xb0\xb2\xd8\xf5\xb2\x71\xc3\x75\xeb\xaa\xaf\xc6\x24\x5d\x6e\xc2\x4b\x1b\xce\xd6\x61\xba\xf0\x0a\xb0\x92\xca\x87\xf9\x94\x1f\xb0\xfd\xba\x3d\x9a\x03\x80\x23\x53\x97\xf3\xfe\xc3\x3d\x9b\xfe\xef\x42\x0f\x0e\xc2\xfb\xe1\x5c\x4b\x01\x1b\x48\x77\xa9\x84\x6e\xd6\x00\x36\x2f\x69\x37\x3a\xc7\x04\x45\x48\x70\x5e\x8f\x63\xaa\x22\xa4\xc3\xf1\x9d\x52\x57\xce\xa8\x13\x4c\x2a\x41\xbd\x17\x0e\x36\xca\x65\x02\x28\x63\xe8\x63\x6a\x73\x7b\x96\xb0\x1b\xc8\x93\x78\xc5\x63\x60\x07\x29\xce\x55\x84\x30\x6e\x20\x67\x67\x02\xb1\x82\x01\x49\x57\x02\xaf\x54\x7a\x1b\xb3\x10\xbb\x7e\x30\xb1\x1e\xbf\x52\xf8\x68\xc6\xfe\xba\x73\x35\xce\x29\xca\x07\x56\x1f\x85\xc4\x3f\xbf\xe1\xd9\xaa\x52\x76\xd1\x4b\xab\x71\x3e\x87\x28\xbf\x70\x86\x99\x46\x4d\x05\xba\xdd\x3a\x7f\x74\x25\xfe\xb4\x4d\xdd\xe0\xbc\x07\x51\xae\x3a\x29\xd1\xef\x9f\xd7\x7d\x47\xbb\x43\x3f\x0e\x34\x2c\x2e\x47\xf8\x7e\xdc\xfb\x9b\xf2\xef\xab\x6a\x4d\xa4\xfb\x14\x78\x79\x09\x80\xde\x2b\xc4\x98\x2d\xe8\xc3\x2d\x99\x3b\x37\xbf\xfc\xf2\xb7\x0f\xd1\x2e\x6a\xaf\xaf\xd9\x7e\xc3\xe5\x17\xbc\x3d\x60\xd3\x7f\x3e\xec\x29\x10\x1c\x22\xcb\x7d\xbb\x8d\x85\x01\xed\x41\xa3\x9e\xcc\xc7\x7f\x62\xac\xc9\x98\xfe\x21\xf6\x66\x92\x15\xb5\x96\xde\x96\x7e\x12\x4e\xb5\x49\xc6\xfb\x14\x06\xd3\x2b\x48\xf8\xd0\xac\x77\x01\xfe\x6e\x7c\x68\x41\x8c\xc1\x8e\x2f\xd4\xe5\x37\x05\xb8\xbd\x6b\xdf\x9c\xe7\x0a\x78\xa7\xb2\x79\x26\x5e\x12\x0b\x8f\x1a\x61\xb5\x7e\xe0\xee\x12\xe7\xbe\xd8\xc9\x6e\x29\xc8\x79\xf5\x41\xe1\x63\x08\x30\x84\x36\xc2\xc9\x74\x42\xfd\x76\x4b\x1f\x4a\x96\x7c\x6b\x0d\x29\xac\x00\x46\x6c\xad\x4d\x1a\xda\x98\x67\x08\x16\xd9\x4d\xc4\x3c\x95\x86\x58\xdf\xda\x0c\x88\xa3\x35\x16\x7c\xc2\xa6\x33\xef\x60\xe6\x9b\x1c\x3d\x12\x86\xb3\xed\x8b\xc6\x3e\x24\x6c\x3d\xa8\xa2\x0b\x0c\x0c\x8e\xc8\x7e\xd7\x29\x0f\x95\x44\xd9\x53\x37\x04\xbb\x32\x5b\xd7\x36\x3f\xff\x1a\x68\xd9\xa0\x95\x95\x4c\x27\xe6\x1e\x68\xeb\x23\x18\x2f\x35\xc4\x6f\x3d\x42\x1e\xe8\x6d\x3d\x85\x40\xd4\xba\x73\xbf\x18\x1f\xf0\x9c\x4c\x77\x4f\xea\xff\x24\xff\x11\x41\x94\x74\xc8\x09\xfa\x99\x21\xa4\x5b\x5a\x92\x8d\x91\x05\xcc\x68\x6f\x6e\x4c\x6f\x6c\x4c\xf7\xd5\x38\x25\xb4\xd9\xf3\x97\xc5\x6e\x23\x52\x1b\x3d\x4c\x25\x79\x8b\xbf\xb8\x53\xa7\x0c\x0d\xbf\x11\x4b\xc8\x2c\x7e\x31\xd0\x1a\x44\x55\x85\xf2\xb2\x94\x51\x2d\x03\x9b\xd7\xef\x69\x04\xa1\xb0\x37\xd7\x3d\x21\x25\x93\x28\x04\x77\xf2\x52\x8f\xd2\x12\xf4\xe9\x63\x07\x29\x03\xb2\x54\x4a\xd3\xba\x77\x08\xb4\x06\xa8\x28\xb7\x35\x50\x78\x0b\x9f\xcc\xac\x63\x27\x4e\x20\xf6\x5d\x12\x6b\x71\xb5\x37\xea\xab\x6d\xb3\xe9\xfc\x22\x93\x06\x4a\x06\x08\xe1\xa6\x3e\xa6\x07\x62\xa9\xe3\xa3\x12\x1a\x17\x8d\xfd\x69\xc4\x83\x83\x03\xd4\x11\x3f\xb6\xa7\xf5\xaf\x57\x35\xf6\xd5\x34\xd8\x69\x59\xda\x44\xba\x6b\x0f\x9e\xe3\x4d\xca\x33\xac\xbf\xea\xca\x35\x1a\x4c\xad\xfc\xf8\x52\xd1\xb9\xab\xf7\x99\xd2\x36\x0d\x2e\x5a\xf0\x5b\x3f\x64\x1b\x6a\xd1\xbf\x35\xdb\xf6\x39\xcc\xf6\x05\xbf\x5c\x1d\x57\x3c\xf4\xae\x72\x71\x5b\x67\x64\xb9\x97\xac\xea\xb7\x2d\xe8\x37\xa3\x7b\xf2\x21\x1d\x9f\x3a\xec\xb3\x85\x47\xda\x26\x43\x72\x8e\x7a\x88\xcd\x73\x46\x45\xa2\xf8\xb9\xc1\xe2\x3b\x5e\xbc\x13\x46\x11\xe5\x19\x7a\x8e\x03\x6b\xca\x73\xfe\xde\x5f\x43\x03\x7b\x1b\x31\xf1\xea\x0a\xd7\x82\x81\xdb\xb9\xd5\x72\x3c\x53\xd6\x42\xb3\x4e\xd7\xd7\x63\x77\x20\x86\xf6\x1d\x67\x9e\x26\xa8\x6c\x29\x49\xe9\x62\xe5\x4f\x67\x1b\x11\x1e\xe7\x03\x8d\x7a\x41\xae\xe5\x9e\x39\xc2\x71\x26\x52\x7a\xbc\xc1\xe4\x77\xf6\xd6\x86\xbf\xb0\x29\xdb\xce\x6a\x42\x16\x10\x89\x0a\xcd\x32\xa3\xae\xba\xd7\xfd\x86\x04\x9f\xa7\xdf\x3f\xa4\xf7\xe0\x82\xb6\x47\x04\xed\x39\x4f\x5d\x27\xa4\x16\x08\x9b\x23\x19\x12\x85\xf5\xd2\x7b\x90\xc5\x44\xd6\xac\x57\xd4\x91\x78\x0f\x08\xc3\xa3\x8f\xa0\x89\xbe\x1a\x31\x6b\x1e\x73\xc3\x9a\x25\x7f\x3b\x97\xee\x52\x3b\xd6\xa0\x80\x0f\x71\xe1\xe2\x63\x3a\x76\x50\x51\xf9\x08\x9a\x96\xd7\x56\x1d\x52\x32\xf4\x4c\x26\x51\xfc\xcb\x3f\x24\x43\x8d\xe0\x2f\x2d\x28\x85\xdc\x7b\x0f\x5c\x86\x5b\x76\x9e\x9d\xba\xcc\x88\xc4\xe7\x0b\x2b\xfa\xf1\x92\xeb\x18\x69\x05\xd4\x8c\x75\xeb\x8c\x9d\x70\x2d\xe0\xaa\x72\xda\xfd\x23\xfd\xf0\x3f\x7f\xf2\x7b\xb2\x7b\xac\xac\x0c\x5d\xc8\x5a\x70\xc0\xcf\xe2\x74\x4a\xc4\xbc\x46\x65\xbe\x54\x8d\x8e\x9a\x21\x99\x9e\x15\xf6\xf0\xd6\x09\xae\x6b\xcb\xa8\x49\x5e\x79\xa6\x97\x1c\xb9\x22\x1f\xbe\xda\x37\x85\x0a\xdd\x4c\x08\x5a\xbf\xf8\x06\xb2\xae\xac\x9b\x71\x4b\xf6\xb5\xe5\x23\x13\xf8\xdc\x5b\x3b\x75\x65\x47\x35\x89\x29\x69\xd6\x4a\xa4\xed\x05\xaa\xdf\x86\xff\x90\x77\xf9\xb1\x7f\xe3\x26\x0d\x2f\x75\xce\xb1\x9a\x30\xc1\x9d\x52\x96\xd0\x05\x8c\x72\x90\x38\x96\xb7\x90\x46\xa3\xd9\x67\xb7\x24\xee\xf8\xcc\xbb\x1e\x54\xd0\x41\x23\x6d\x6c\x18\xe5\x4e\xcb\x3a\xed\xf6\x16\x17\x54\xaa\xba\xd7\xc6\xb7\xdb\xb6\xd7\x62\x79\x7f\x50\xdb\x23\xaa\x89\x42\x71\xf0\x87\x5a\xc9\xc5\x9a\x69\xbc\xf7\x84\x4e\x6a\xde\xdf\xee\x10\x62\x42\xe9\xff\xd6\x0f\x3e\x95\x4c\x9d\xdb\x98\x98\x29\xe7\x5c\x5d\x29\xa5\xbd\x79\xa3\xbe\x3b\xa5\xa8\xee\xc0\xfe\xb0\xa2\x1f\x77\x83\x89\xec\x5e\x47\xa7\x15\x25\x56\x8b\x30\x1c\x32\xc1\xaa\x16\x85\x7a\x57\xe2\x6e\x71\x23\x6a\xd8\x90\x79\x25\xfa\xf5\xdf\x83\x1a\xd3\x0c\x9b\x09\xaa\x04\xfa\x82\x51\xa5\x1f\x1e\x41\x27\xd0\xdf\x4f\x02\x1a\xe2\x09\x04\x1b\x0a\x3b\xf8\xed\x93\x30\x75\x28\x31\x61\x0d\x7e\xba\xca\x88\xef\x18\x18\x61\x7a\x58\x4e\xb3\xbc\x26\xae\x66\x83\x27\x73\x48\xd4\xe2\xee\x95\xc5\xbf\xbd\xfe\xbe\x22\x59\x1d\xed\x03\xed\xcb\xe4\x76\x5d\x35\x98\xf9\xd9\xae\x12\x91\x95\xd4\xd7\x93\x70\x7a\x89\x0b\xb5\x00\x5c\x80\x5f\x17\x33\xf0\xff\xe3\x37\x1d\x1d\x01\x2b\xf5\xec\x40\xc2\xea\x2f\xef\x0e\x29\x5f\xe9\x4e\x40\x22\xd2\x4e\xb4\x88\x09\x50\x92\xc4\x7c\x71\x79\x49\xe8\x7b\x3a\x0e\x27\x5f\xf3\x47\x22\x71\x9a\xc0\x60\x0c\x1d\xd3\x7f\x35\xff\x5a\xcf\xa7\xe3\x5d\xfb\x97\x5c\x49\x40\x90\x31\x39\x85\x2f\x10\xe0\x57\x47\xfe\x90\x94\x8f\xec\xee\xea\x82\x53\xf7\x46\xab\xbd\x05\xdc\xac\x27\x82\xb6\x58\xc1\xe0\x72\x15\x63\x3f\x04\x18\x60\xd3\x00\xaa\xff\x5f\x83\x59\x0c\xd8\x01\x0a\x02\xdd\x81\x17\x64\x52\x64\x77\xc9\xca\xc9\xd6\x48\x1c\xf0\x1f\x97\xef\x01\x00\xff\xa3\x20\xfb\xe3\xe3\x01\x01\xa4\x27\x0f\xad\xef\xbf\x9e\x34\x28\x7d\x4c\xaf\x47\x8d\x59\xbb\xd3\x03\x3b\xc5\x6a\xc6\x3c\x1f\x6a\x69\xc2\x30\xc9\x45\xd4\x86\xd1\x64\xb5\x4e\xa0\xd2\xef\xf2\x3f\xf2\xc8\xc8\x70\x1d\x76\xb1\x21\x62\x4f\xe8\x55\x93\x25\x96\xeb\x4f\x64\x8b\x12\x1b\x72\xd3\x46\x5b\xdc\xf6\xe6\x5b\xf2\x00\x0a\x03\xf2\xcc\x72\x96\x39\xe3\xf1\x2c\x29\x6c\xde\x6f\x62\x35\x94\x15\xc4\x27\x6f\x28\xd5\xa4\x11\x38\xb9\x8a\x53\x2c\x07\xcc\x4f\xe5\x07\x64\xe7\x79\xfc\xed\x06\x28\x54\xad\xd4\xcd\x53\xd8\x51\x07\x5b\x56\xcb\x06\x45\x4a\xe2\xcb\x9a\xf6\x8a\xe2\x93\x8b\x8a\x35\x69\x5c\xa4\x1b\xc3\xa4\x5d\xa1\xe6\x03\x65\x0a\x96\xed\xf9\xbc\x1f\xe7\xcc\xd7\x17\xb5\x9b\x22\x8f\x35\xeb\xb2\xb4\x2f\xb5\x95\xaa\x83\x2d\xfb\x45\x26\xcc\x74\x37\x2a\x56\x24\xbc\x5e\xa2\xc4\x55\xf2\x88\xa3\xf1\x1e\x55\xed\x6a\xe3\x4d\xca\x90\x52\xad\xaf\x05\xde\x6f\x38\x75\x4a\x86\x98\x8a\x74\x3f\x63\xbd\xa7\x4c\x73\xe3\xfa\x9b\x97\x7f\xb7\x86\x76\x24\x2b\x4d\x1b\xba\x38\xff\x30\x00\x8b\x6b\x6c\x68\x1b\xf5\x74\x85\xd6\x35\x7e\xff\xed\xfa\xfd\x5b\x24\x51\x03\x9d\xc2\x02\x61\xbc\x66\x0e\xa1\x55\x8f\x39\x8a\x47\x53\x8a\x35\xfc\xe2\x25\x47\xbb\x52\x49\xcb\x5b\x53\x4b\x9d\xdc\xf2\x08\x17\x7d\xc3\x23\xee\xea\xdf\xaf\xa2\xca\xa4\xcd\xee\x3d\x98\x9c\xb9\xc3\xbd\x14\xd6\xb4\x99\x50\x86\xdf\x36\xb5\x90\x0c\xab\x6f\x3b\xc0\x37\x7c\xe1\x15\x7a\xfb\x4a\x22\x75\x61\xd7\x55\x25\xfd\x35\xcf\xa4\xc4\xce\x6f\x9f\x6f\x8a\xd9\xf3\xd5\x1a\xd8\x16\xcf\x85\x67\x42\xad\x8c\x90\x60\x4f\xaa\x71\xb4\x8a\xfc\x33\x6a\x62\xfb\x8a\x99\xe8\xae\x4a\xfe\xdb\xcb\x5f\x1d\x5c\x4b\x2e\xb1\x28\xd2\x7b\xf7\x1e\x54\xa7\x7f\x80\x80\x50\x4c\x44\x8a\x56\xce\x67\xa4\x81\x75\xab\xd8\x84\x8f\x2d\x57\xa7\x9b\x73\xfb\xd2\x4a\x8d\xca\xa2\xc6\x13\x7a\xc8\xe3\x75\xba\x92\x29\x44\x56\x32\x6d\xad\x35\x1b\x9f\x58\x88\xe5\x96\x3d\x91\xbf\xf6\xd7\x42\x67\x5d\x71\x75\x83\xdf\x81\xf8\xc0\x92\x69\x42\x5c\x61\x8a\xa8\x5e\x20\xc8\x1e\xc3\x4c\x46\xea\x89\xde\xff\xd2\xed\xcb\x23\xe8\xcc\xcb\x8b\xbe\xb3\x06\xee\x2f\x82\x43\xe0\x90\x21\x0a\x0e\x76\xab\x22\x39\x29\xa4\xbb\xba\x3b\x3d\x73\xa8\x00\x08\x04\x12\x90\x4a\xca\xeb\xc6\x94\xd2\xa0\x75\x1c\x7b\xc1\x09\x29\xf8\x47\xa3\x42\xe2\x1c\x53\x6a\x6f\xed\xe1\x74\x90\x64\x51\x7a\xce\x21\x6e\x06\x04\x7f\xba\xda\xab\x74\x9c\x0e\x96\x72\xf5\x72\x9a\x4e\xb4\x9d\x23\x8f\xcd\x0e\x40\x39\xc9\xf3\x86\xf4\xcf\xfc\x0f\x4c\x4f\xa8\x44\x98\x0e\x00\x00" - -func font_fontello_woff_gz_bytes() ([]byte, error) { - return bindata_read( - _font_fontello_woff_gz, - "font/fontello.woff.gz", - ) -} - -func font_fontello_woff_gz() (*asset, error) { - bytes, err := font_fontello_woff_gz_bytes() - if err != nil { - return nil, err - } - - info := bindata_file_info{name: "font/fontello.woff.gz", size: 3701, mode: os.FileMode(438), modTime: time.Unix(1432348676, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _index_html_gz = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x0b\x65\x50\xc1\x4e\xc3\x30\x0c\xfd\x95\xd0\xeb\x68\x23\x6e\x1c\x92\x72\xd8\x40\xe2\x80\x40\x30\x0e\x3b\x66\x89\xdb\x1a\xdc\xa4\x8a\xcd\xa6\x4a\x7c\x3c\xd9\x3a\x24\x24\x2e\xd6\x7b\xcf\xcf\x4f\x7a\x36\x57\x9b\xe7\xf5\x76\xf7\x72\xaf\x06\x19\xa9\x35\xa7\xa9\xc8\xc5\xde\x42\x2c\x0c\x5c\x68\xcd\x08\xe2\x94\x1f\x5c\x66\x10\xfb\xbe\x7d\xa8\x6f\x2f\x5a\x74\x23\xd8\x03\xc2\x71\x4a\x59\x94\x4f\x51\x20\x8a\xad\x8e\x18\x64\xb0\x01\x0e\xe8\xa1\x3e\x93\x6b\x85\x11\x05\x1d\xd5\xec\x1d\x81\xbd\xa9\x5a\x23\x28\x04\xed\xe3\xeb\xda\xe8\x05\x1a\xc2\xf8\xa9\x86\x0c\x9d\xad\xb4\xee\x4a\x1a\x37\x7d\x4a\x3d\x81\x9b\x90\x1b\x9f\x46\xed\x99\xef\x3a\x37\x22\xcd\xf6\xe9\xb4\x87\x9c\x9d\x7c\x6f\x72\xc2\xb0\x7a\x73\x91\x57\x45\x4d\x95\xca\x40\x96\x65\x26\xe0\x01\x40\xfe\x06\xef\xbf\x62\x20\x68\x4a\xce\x3f\x93\x5e\xca\xee\x53\x98\x5b\xc3\x3e\xe3\x24\x8a\xb3\xff\x3d\xf9\xe0\x62\x59\xe4\x02\x16\x97\x3e\xff\xec\x07\xf7\x87\x06\xb5\x43\x01\x00\x00" - -func index_html_gz_bytes() ([]byte, error) { - return bindata_read( - _index_html_gz, - "index.html.gz", - ) -} - -func index_html_gz() (*asset, error) { - bytes, err := index_html_gz_bytes() - if err != nil { - return nil, err - } - - info := bindata_file_info{name: "index.html.gz", size: 241, mode: os.FileMode(438), modTime: time.Unix(1432348676, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -// Asset loads and returns the asset for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func Asset(name string) ([]byte, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) - } - return a.bytes, nil - } - return nil, fmt.Errorf("Asset %s not found", name) -} - -// MustAsset is like Asset but panics when Asset would return an error. -// It simplifies safe initialization of global variables. -func MustAsset(name string) []byte { - a, err := Asset(name) - if (err != nil) { - panic("asset: Asset(" + name + "): " + err.Error()) - } - - return a -} - -// AssetInfo loads and returns the asset info for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func AssetInfo(name string) (os.FileInfo, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) - } - return a.info, nil - } - return nil, fmt.Errorf("AssetInfo %s not found", name) -} - -// AssetNames returns the names of the assets. -func AssetNames() []string { - names := make([]string, 0, len(_bindata)) - for name := range _bindata { - names = append(names, name) - } - return names -} - -// _bindata is a table, holding each asset generator, mapped to its name. -var _bindata = map[string]func() (*asset, error){ - "bundle.css.gz": bundle_css_gz, - "bundle.js.gz": bundle_js_gz, - "font/fontello.eot.gz": font_fontello_eot_gz, - "font/fontello.svg.gz": font_fontello_svg_gz, - "font/fontello.ttf.gz": font_fontello_ttf_gz, - "font/fontello.woff.gz": font_fontello_woff_gz, - "index.html.gz": index_html_gz, -} - -// AssetDir returns the file names below a certain -// directory embedded in the file by go-bindata. -// For example if you run go-bindata on data/... and data contains the -// following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then AssetDir("data") would return []string{"foo.txt", "img"} -// AssetDir("data/img") would return []string{"a.png", "b.png"} -// AssetDir("foo.txt") and AssetDir("notexist") would return an error -// AssetDir("") will return []string{"data"}. -func AssetDir(name string) ([]string, error) { - node := _bintree - if len(name) != 0 { - cannonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(cannonicalName, "/") - for _, p := range pathList { - node = node.Children[p] - if node == nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - } - } - if node.Func != nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - rv := make([]string, 0, len(node.Children)) - for name := range node.Children { - rv = append(rv, name) - } - return rv, nil -} - -type _bintree_t struct { - Func func() (*asset, error) - Children map[string]*_bintree_t -} -var _bintree = &_bintree_t{nil, map[string]*_bintree_t{ - "bundle.css.gz": &_bintree_t{bundle_css_gz, map[string]*_bintree_t{ - }}, - "bundle.js.gz": &_bintree_t{bundle_js_gz, map[string]*_bintree_t{ - }}, - "font": &_bintree_t{nil, map[string]*_bintree_t{ - "fontello.eot.gz": &_bintree_t{font_fontello_eot_gz, map[string]*_bintree_t{ - }}, - "fontello.svg.gz": &_bintree_t{font_fontello_svg_gz, map[string]*_bintree_t{ - }}, - "fontello.ttf.gz": &_bintree_t{font_fontello_ttf_gz, map[string]*_bintree_t{ - }}, - "fontello.woff.gz": &_bintree_t{font_fontello_woff_gz, map[string]*_bintree_t{ - }}, - }}, - "index.html.gz": &_bintree_t{index_html_gz, map[string]*_bintree_t{ - }}, -}} - -// Restore an asset under the given directory -func RestoreAsset(dir, name string) error { - data, err := Asset(name) - if err != nil { - return err - } - info, err := AssetInfo(name) - if err != nil { - return err - } - err = os.MkdirAll(_filePath(dir, path.Dir(name)), os.FileMode(0755)) - if err != nil { - return err - } - err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) - if err != nil { - return err - } - err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) - if err != nil { - return err - } - return nil -} - -// Restore assets under the given directory recursively -func RestoreAssets(dir, name string) error { - children, err := AssetDir(name) - if err != nil { // File - return RestoreAsset(dir, name) - } else { // Dir - for _, child := range children { - err = RestoreAssets(dir, path.Join(name, child)) - if err != nil { - return err - } - } - } - return nil -} - -func _filePath(dir, name string) string { - cannonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) -} - diff --git a/server/serve_files.go b/server/serve_files.go index 29d41666..3b001a3d 100644 --- a/server/serve_files.go +++ b/server/serve_files.go @@ -8,6 +8,8 @@ import ( "strconv" "strings" "time" + + "github.com/khlieng/name_pending/assets" ) var files = []File{ @@ -41,7 +43,7 @@ func serveFiles(w http.ResponseWriter, r *http.Request) { } func serveFile(w http.ResponseWriter, r *http.Request, path, contentType string) { - info, err := AssetInfo(path) + info, err := assets.AssetInfo(path) if err != nil { http.Error(w, "", http.StatusInternalServerError) return @@ -51,7 +53,7 @@ func serveFile(w http.ResponseWriter, r *http.Request, path, contentType string) return } - data, err := Asset(path) + data, err := assets.Asset(path) if err != nil { http.Error(w, "", http.StatusInternalServerError) return diff --git a/storage/storage.go b/storage/storage.go index 6fc1f291..8dc5e6d5 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -10,7 +10,7 @@ import ( ) var ( - appDir string + AppDir string db *bolt.DB @@ -26,18 +26,18 @@ func init() { log.Fatal(err) } - appDir = path.Join(currentUser.HomeDir, ".name_pending") + AppDir = path.Join(currentUser.HomeDir, ".name_pending") + + os.Mkdir(AppDir, 0777) + os.Mkdir(path.Join(AppDir, "logs"), 0777) } func Initialize() { var err error - log.Println("Storing data at", appDir) + log.Println("Storing data at", AppDir) - os.Mkdir(appDir, 0777) - os.Mkdir(path.Join(appDir, "logs"), 0777) - - db, err = bolt.Open(path.Join(appDir, "data.db"), 0600, nil) + db, err = bolt.Open(path.Join(AppDir, "data.db"), 0600, nil) if err != nil { log.Fatal("Could not open database file") } @@ -56,5 +56,6 @@ func Close() { } func Clear() { - os.RemoveAll(appDir) + os.RemoveAll(path.Join(AppDir, "logs")) + os.Remove(path.Join(AppDir, "data.db")) } diff --git a/storage/user.go b/storage/user.go index 1afb66f4..2ac7fe96 100644 --- a/storage/user.go +++ b/storage/user.go @@ -304,7 +304,7 @@ func (u *User) SearchMessages(server, channel, phrase string) ([]Message, error) func (u *User) openMessageLog() { var err error - u.messageLog, err = bolt.Open(path.Join(appDir, "logs", u.UUID+"_log"), 0600, nil) + u.messageLog, err = bolt.Open(path.Join(AppDir, "logs", u.UUID+"_log"), 0600, nil) if err != nil { log.Fatal(err) } @@ -315,7 +315,7 @@ func (u *User) openMessageLog() { return nil }) - indexPath := path.Join(appDir, "logs", u.UUID+"_index") + indexPath := path.Join(AppDir, "logs", u.UUID+"_index") u.messageIndex, err = bleve.Open(indexPath) if err == bleve.ErrorIndexPathDoesNotExist { mapping := bleve.NewIndexMapping()