From bbefcef53bf2ef420bf7a68253fea5d223d37a44 Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Sun, 18 May 2014 12:05:17 +0200 Subject: [PATCH] Allow node IDs with spaces/dashes in config. Use dashes in GUI. (ref #230) --- auto/gui.files.go | 4 ++-- config/config.go | 16 ++++++++++++++ config/config_test.go | 50 +++++++++++++++++++++++++++++++++++++++++++ gui/app.js | 4 ++-- gui/index.html | 8 +++---- 5 files changed, 74 insertions(+), 8 deletions(-) diff --git a/auto/gui.files.go b/auto/gui.files.go index f21fe301f..be04a67b7 100644 --- a/auto/gui.files.go +++ b/auto/gui.files.go @@ -18,7 +18,7 @@ func init() { bs, _ = ioutil.ReadAll(gr) Assets["angular.min.js"] = bs - bs, _ = hex.DecodeString("1f8b080000096e8800ffd43c5b6fdbb6f7eff9149cd74d72ebdac9b00d7fd44d872ded86fcbb5ed0ac7d09f2205bb4ad46a6348a6a6a64feeebf73484a26454a5692b6eb0c6cb1c9c373e7b9505427f7df1769c20499f1ecaaa0fc1111bca42332cf98485849abdf795a16f89ffa4dee4f0e26f79769368b5272ef115944690140115b9669c4f56f043a084af852089ecc45303d38f81071526cd85cac12b624c7d58af13a8bcb9486413d178cc8f9c5702a17943c9d4580e698049c16880747395dc0afd52913947f00368ec9d1217ca6643221ebe2e0a0463546597896a69487c159357a22780a441625fc4e3246c27bc53ccb41887b2b21f221b93e20f0414239a71f9e4602e91f4eeb51e424e2428921e505f17052e1192fa978f51ca6505d537302b86154d22c60fa7adb9c5c244b777cbd397d8af207d628cb628a48ce2f3c484e19caeae380729e71cfba8252f60ce75c4a601f9aba6c719a671e29d2a8106ff3187416c324a35704f5170e2da01505f5cd6824945ee51498ee0c7c852d0b32a38b8c5332cbb2b42069965dc2880053db0c0b21814114397e9dc48f48f0675208ca0011d81714340787947627af7926b279961205417e8d633063410b00149b1c9c3d10f4a3805fdabacadbb72303f98be8e31965f1f3595e18e85f956299a12fbc4147f93359278284cf7fcb8be10e352bd733ca3b91bf017411ab5cfacc20a06648edede18d316bbff323d793b7c7ff3ae211ecb0f40dfdbb04205337a03102fa81952c962ada81f4c70f484e56102d6843f188fcf724a544cd2afdf7d6bc41e00f19cc7e65ec198b66298d0d1a6a8ac05c06d182eef0a2737672fd67366fc129676e83f20cc77f53c1daf46f1c26bb71139db5feed6bf6da65478d109cf42fbe6844b73239f36f3ebda74cf5bd3dbdcb867b6b0b8ad87e2dc58a427e9a473274bfb544de8bf075541457198fbb911a501a71be1bf121af34546714c80067e57c4e694ce3b04a28bda3247e920509bf31f38989c5c094b04498ebe454187ccba800862f654c0f8618c4a3340c56494c8326745bd2c2cfd6626897f86ec8cd6e61372fbecc6ab3b27535fd7b0441c0567337b39c8a92b336213b95dea6d9eb5934bf8c799683b30059702570954bba9965118f7551b4ed567c435c03a2912ebb1552033b0ab104f39aef5e94e7e926dc15464df95b980a9db107e46848be233fd9f2981ab0b8af6b0a59d7a132bc2cc8fa0c0508abbaf0010926c50602cc1a4c51e0962b0a837fd8615153067b6f7a15ae30021bb8de6079a8eaa70e0519ee68aedb7d7f357b0fc9760cae51846625351c43cdf32c9aaf0ce449ecf89f5701b242fb05d11c073040d91c06debe393dc9d679c620b021a6beea31d420f19e27f185a309c798c6773f8f46e9dbdb52586bb3ec0aa863748492f72a1c8e2c0881e13344988775ad3e2413d90ed89049ac6374f5314a7b58ef75838441c161ef3963362b453d6dcd8321d1762461a44dc132bae3e4781515afae1854a739e562230de581c74fd5964d9dd9ad3322f8a6050b124593d6c2bd88c46abc8e3e868723f27fe4beb284843865bf6d042dfeca04942b0f3d3d8c0385aa17f1d0e5d0a25c2bae9d34d48c7d685b60adc4b704f2fa7c4542daa65a4729877d45f000bad6b0dce9c171839c8bc1763073811a6aec439f73da9d66338ceddbacaa4becbd4f9bbda59fdc767ad0ec1fa172156561857b1c6e262e2cc2b2851d95100ee2d231b4ab258be9226150d4fa133dd491ec12f6380bccece34b8d066ab00df442b08bbf4112ad98cf4496e740d98b599e78081563028ccc1e32727eb7ba02977fcf0f2fc6227b0b04f809980692cd033501769915828747c3a92d875e7e4c06d8f442e93320fffc4376a3a7714a074d59d434b8d98084831d977888f29af239e48f6849b5611e90c177c381575aad1243a06672cfb313287cbf80bdb10f7898b045f6192c2e71c7d870f24f6675cb74410246ea26afb765d056c2ee7015ca0dbad1e53c59477ce345d7a652dbb6b6af7c7603437adf53bd9bca566795325148fc87fdb05a06cde7429d32429af2ba0eee374562e20330789836752bd3e09c26690854fcc1124ffb3cc112874f16567f83cc62f007384fd2d40bc62fe1efe9d30bdb0311b0a99a6a7c8cb5644a2559d42168c2974c2b6f3965041512343215a17836dcbe4c072d12e2b6699285c4f4ddb089b12310054f9342cb5e07688f5a4fe728d27f41a9d9e54df5a9fba99b286d0d2566d1ae2d37807fb5ea7283642f9db9c170afceccb0e8aa0c0fbebeb0c634635269fadcad2bb6ffd2616f43e5ff9a088d20d099a7da457947f79a0199b139958e663c88696153437ca0bc00dc3efe3ea77ad204f2eebb76da3decfc325ad31b6907e05b7832413ab8b145ae2a5ae8047ff6a740b14a8a973e4e9b4e583d196bac6b1eaeea1a4443db650716cd72629c52b6142b2809f13ccb2bee202c55772157d8b571932d90571e370066a8eda75f8966699c08e344bfe5e82d0cbead9eb9f53df59427e4436fbd187da0fb497a1f69368e492da0f1ab5ceea7b17ae6a0439fb5e55ca833c1c7459e26220c462859941bedee4760a8d2ebc7b180dc007ee4e9a0f3ac70cebb8014a8e3ffcf5ebd1c17f2c966b2d8841627c311b95ed12886adfb885c072719037ec4c3bfc0350350299ec6ea671293f745c682ad45d86791019eaa0fda3a6e7920deaa6febf0dd7e0cd076865facb2ab60bf32f4520b72cff36a8f8fa23fef8b5115da9273d0a45e716f0ccd0b657178bd1d55bbc36505498070cf3e8257787560819dd174a1ce1e1be9c2ca16aebc3bc6c6f51331f0401d1610533d3c7e9f250c9c9278f486c0cf80938c8fef8113bce692692bc8a1cd2ab5dd6ac7da1688e2d831c05ecd5f9b3202c978c3a235d0dcf6d0be7fa3dbeaf7c37c79e540a34705edd68f8fa2f310cc7cecd750c9fea7583e3d18d14f65b445920a6a3ec268ab2d58e5d3dfec9cda745f35db72ac68c5db971e3e8c832b795e8e29529d99abc721fe234639274f421b381b133da4bc83a44d695dcdefc959ff46ca68782c66e04e7f356a9611893346472499de54d05e3ebfab8c5cdd3b5075a06d9639e0016934a7e1844c80e100c8e96ced60a863922fe8deb21aa889a0a65c45a84742f2790149c8637b47aa1a13261e3cf0b5be26ec7972613626b60a3a9ee4558b77124f1d50cdb99df4aacf8cd3e8b2474bac1e6c01a6960dac24cecb6215ba89b825828d8b8c8bb0ea46234e6f1b68be867d978915e5159f6d7598d953b646edde411b2b11374cb7b4579df12081f2a919b86fe1d5ac612270cca9e3f6ac67076e087fce2eda5dd423b37c60854d404f53a8075cae2ddafa353afe2b8166f58973c972af35e6298df8b3ea795a67c165dedcb4f83cb7b9d69dec43727421d9da9b8ee4ba89e424f073b9e00954d5e9c67567d84426abbb0c7f73679107276676f0bb4c216b68f87f9d08e675601c354f3a706ee8dc45312c07785a5aa83cebe330159c7dc5c3d709637a7c03b3376b6cf48a5d635340018ae7dcd21410a0b65d9d8e81a42a979cbb274ebde4596b113daf36ec857b89ecd6cd16eaad67258f1c7d9a36c731c75e3b78d47feb06e7cb8b8ca560a7cceace7b9e7d8a52d0e2d929053515a714c4550e549deecf2fdc39db378dfce1ba671d9d984a38ba0771b0f88a333f39566d846345cb9fb30c21544574ad36d023cd48f3be60339be147359e7e7e5d13a92ea90256bad0bfda4a2ad47c81de984855b705b6afaac6524ae9dec6bddcf1d374e3da46960d3cd1d43af7bfa311fe2b5d28de17366cd4e3b2a77ec472d3bb497a99f772d21e8a37bc5e5adf88f05e213520f47b3df216a05ba2ef614a5be9864cd5af18b532d57642bee70c5db7cfd689656bfbe7e0d2d1aa0dded7ffb51e0ee9edf102faf6f63dd48a403e2e6f5edded658a095e81b99d3dea0d2a5dc11cdbdb2754f7ede518540bd53b3ca12dd1a8f9c69cc666aea8ef6e8fc88f3f1d028014bd16c3507f188dc8ac92c8789416c90753eafa94f12cedfbef89069879019a8f18359ac71a7ce8ebac1e1e4d9b25b75ef6442fab6a6d03abcaee12af735ed2c0abd6ed30aba54feaa5a01d43373285b6e8261a3f4d38e4e48c6f24e9fa577fea3b044f4c042e0fe8f4a9f9fae2da783f2ff514f95693b63ee75549a0d9d05ea21959bb0465125a9b1453a31c6b9cebae4d62a9aa78d678643b34844ed56637346a3391da4cc4749eac21ad0199141a9ed2e2254e968928f04d9f79550ba145e40ba3cd6b601afda1d5a22904d545e5459a653c945fd36ca9be4433497a88778feb99a3c3aab744ca8d7bcec023f4e00ab32d9a62736bbebdaa4f1a0216014464bfb35a71af571b6f0db0bc844d2cef327a4494d36391fd9e7ca471582bd05ab50b363208b80ccd12867764faf3d3dce472509aa10e046d57140f49eb3d4785e509393afce14772dffce3d4ea127272ec019dfaa8766be98721de840dc81fc94d58ebc3d31d9879d18f994e2eee40feb99fbc79c7916760ecca1f704db0cfcfd6145f1fff8afc4c5e0035fe7468b3097a173fbb09677d58ba8b9bf5e2a593893b50bffc0c4e56ac20e5dcd2c72ce6bd376d5a8846e955b4295e566f277f7efff6de9836d9dfc7f17c55b2cbd3a79f98591fab03e31295bc7c0d9529e651a5e535becc134ec6d747a39fb79365b35d97c07bd1ea2109acbb96fa9ac5b6a98158965cc9071a06996c7bd4f95c97264c0f51ff0406b4c527c1c81896a7d4fadfd8a887058f58314fcbd8999105fda3e6ab1beafe0fe03ed65f0d125b032d5d033981af323f5656c092fc7880b7fa07842d1fcabbeac703bbb93bd738c750a40d9e3c9ec8954f3405d7510c35952cf9bb9427308692ba74f477098bf175fde50be4c490224dd8e5a31d0ea98611a1e97a44222138d47773c1d3a6d3e3d8f81e98b780c67f5cb262952c445df9861f127af52e4afd2773f20d8a3e673ed56732215794401829d39805421551a06d2fb0e20c34fb0ea112b169684b9e174e9da5fadef28e37758e540b72d1c19c58a91342425190824429a751bcb9157bf210a99dbffd3c240551083fa9769c11ed63b57e1a47a9ee8bc8ca9dff070000ffff010000ffffc5f4a78114470000") + bs, _ = hex.DecodeString("1f8b080000096e8800ffd41c5d6fdbb6f63dbf82f3ba496e1d3b19ee868bbae9b0a5dd90dbf503cdda97200fb245c76a644aa3a82646e6ff7ecf21299914295949daae33b0c5260fcf37cf074575f2f04391264c9019cfae0aca1f13c14b3a22f38c898495b4fa9da76581ffa9dfe4e1646ff2f022cd66514a1e3c268b282d00286217651a71fd1b81f68212be14822773114cf7f63e469c146b3617cb845d90a36ac57895c5654ac3a09e0b46e4ec7c38950b4a9ece22407344024e0bc483a39c2ee0d7f28409ca3f021b47e4f0003e5332999055b1b757a31aa32c3c4b53cac3e0b41a3d163c05228b127e271923e183629ee520c483a510f990dcec11f820a19cd38fcf2281f40fa6f528721271a1c490f2827838a9f08c2fa878fd02a6505d537302b86154d22c60fa66d39c5c2417eef86a7df20ce50fac5196c514919c9d7b909c3094d5c701e53ce39e7505a5ec39ceb994c03e3475d9e234cf3c52a45121dee531e82c864946af08ea2f1c5a404b0aea9bd14828bdca2930dd29f80abb28c88c2e324ec92ccbd282a459760923024c6d332c84040651e4f84d123f26c11f4921280344605f50d01c1c52da9dbce199c8e6594a1404f9258ec18c052d0050ac7370f640d06b01bfb47595b76f4606f297d1f52965f18b595e18e85f97e222435f788b8ef247b24a04095ffc9a17c32d6a56ae669477227f0be82256b9f4a94140cd90dadbc35b63d67ee747ae27ef8eff4dc423d861e95bfa570940a66e406304f4032b592c55b405e98f1f901c2f215ad086e211f96f494a899a55faefad7983c0ef3298fdc2d87316cd521a1b34d41481b90ca205dde245e7ece4fa8f6cde8253cedc05e5298effaa82b5e9df384cb6e3263a6bfdbb37ec8dcb8e1a2138e95f7cde886e6572eadf7c7a4f99ea7b77729f0df7ce1614b1fd528a2585fc348f64e87e6789bc13e19ba828ae321e772335a034e27c3be2435e69a8ce2890014ecbf99cd298c66195507a4749fc240b127e63e613138b8129618930d7c9a930f89651010c5fca981e0c31884769182c9398064de8b6a4859f8dc5d036f1dd929bedc26e5e7c99d56665e36afab7088280ade66e66391525676d42762abd4db337b3687e19f32c076701b2e04ae02a97743dcb221eeba268d3adf886b80644235d762ba40676146209e635df8328cfd375b82d8c9af2b730153a638fc8e1907c477eb4e5313560715fd714b2ae4365785990f5190a105675e123124c8a3504981598a2c02d571406ffb0c3a2a60cf6def42a5c61043670bdc1f250d54f1d0a32dcd15cb7fdfe7af60192ed185ca308cd4a6a38869ae779345f1ac893d8f13faf026485f633a2390a6080b2390cbc7b7b729cadf28c4160434c7dd563a841e23d4be27347138e318def7e1e8dd2b7b7a5b0d666d91550c7e80825ef55381c591002c3678830fb75ad3e2413d90ed89049ac6374f5314a7b58ef75838441c161ef3963362b453d6dcd8321d1762461a44dc132bae3e4781915afaf1854a739e5622d0de581c74fd5964d9dd98d3322f8ba050b124593d6c2bd8cc472bc8aaec38311f92f79a82c21214ed8af6b418b3f3301e5cabea78771a050f5221eba1c5a946bc5b593869ab10f6d0bac95f886405e9f2f4948db54eb28e5a0af081e40d71a963b3d3a6a907331d80e662e50438d7de8734ebbd36c86b15d9b557589bdf769b3b7f493db4cf79afd2354aea22cac708fc3cdc4854558b6b0a312c2415c3a8276b564315d240c8a5a7fa2873a925dc21e6781997d7ca9d1400db6815e0876f13748a215f3a9c8f21c287b31cb130fa1624c8091d94346ce6f5757e0f2efd9c1f95864ef80003f06d340b279a426c02eb342f0f07038b5e5d0cb8fc8009b5e287d06e4efbfc976f4244ee9a0298b9a06371b9070b0e5120f51de503e87fc115d506d984764f0dd70e09556abc410a899dcf3ec180adf2f606fec03f613b6c83e83c525ee181b4efec9ac6e992e48c048dde4f5b60cda4ad82dae42b94137ba9c27ab88afbde8da546adbd6f695cf6e6048ef3baa7753d9eaac52260a89ffa01f56cba0f95ca8534648535ed7c1fda6484c7c00060fd3a66e651a9cd3240d818a3f58e2699f2758e2f0f1c2ea6f90590cfe00e7499a7ac1f815fc3d79766e7b20023655538d8fb1964ca9248b3a044df89269e52d278ca0428246a62214cf86db97e9a04542dc364db29098be1b36317604a2e0595268d9eb00ed51ebc91c45fa372835bbbcad3e753f751ba5ada0c42cdab5e506f0af565d6e90eca5333718eed49919165d95e1c1d717d698664c2a4d9fbb75c5f69f3bec6da8fc1f13a111043af354bb28efe94e33203336a7d2d18c07312d6c6a888f941780dbc7dfe7544f9a40de7ddf4ebb879d5f452b7a2bed007c0b4f26480737b6c855450b9de04ffe14289649f1cac769d309ab27638d75cdc3555d836868bbecc0a2594e8c53ca2ec4124a423ccff28a3b084bd55dc815766ddc640be495c70d80196afbe957a2591a27c238d16f397a0b836fab676e7d4f3de509f9d05b2f461fe96e92de479a8d63520b68fc3a97fb69ac9e39e8d0676d3917ea54f07191a7890883114a16e546bb7b0d0c557abd1e0bc80de0479e0e3acf0ae7bc0b48813afe77fafad5b8904f3693c53ab438198ec8cd9246316cddc7e42638ce18f023f6ff04d70c40a5781aab9f494c3e14190b3616619f450678aa3e68ebb8e58178abbeadc377fb3140db197eb1ccae82ddcad04b2dc81dcfab3d3e8afebc2b4655684bce41937ac58331342f94c5e1cd6654ed0e97152401c23dbf06aff0eac0023ba5e9429d3d36d285952d5c79b78c8deb2762e0813a2c20a67a78fc214b183825f1e80d819f0327191f3f002778c325d35690439b556abbd38eb52d10c5b163809d9abf31650492f19a452ba0b9e9a17dff46b7d5ef87f9f2ca81468f0adaad1f1f45e72198f9d8afa192dd4fb17c7a30a29fca688b2415d47c84d1565bb0caa7bfd93ab5e9be6ab6e558d18ab7af3c7c180757f2bc1c53a43a33578f43fc478c724e9e84367036267a48790f499bd2ba9adf91b3fe8994d1f058ccc09dfe6ad42c2312678c8e4832bdada0bd7c7e5b19b9ba77a0ea40db2c73c003d2684ec3099900c30190d3d9dac150c7245fd0bd63355013414db98a508f84e4f302929027f68e5435264c3c7ae46b7d4dd8b3e4dc6c4c6c15743cc9ab166f259e3aa09a733be9559f19a7d1658f96583dd8024c2d1b58499c97c5327413714b041b17191761d58d469cde35d07c0dfb2e134bca2b3edbea30b3a76c8ddabd833656226e986e69af3ae34102e5533370dfc1ab59c344e09853c7ed59cf0edc10fe8c9db7bba84766f9c00a9b809ea6500fb85c5bb4f56b74fc6702cdea53e792e54e6bcc531af1e7d5f3b4ce82cbbcb969f1796673ad3bd97d72782ed9da998ee4ba89e424f073b9e00954d5e9da7567d84426abdb0c7f7b679107276676f0bb4c216b68f87f9d08e675601c354f3a706ee8dc45312c07785a5aa83cebe330159c7dc5c3d709637a7c0bb3b76b6cf48a6d635340018ae7dcd21410a0365d9d8e81a42a979cbb274ebde4596b113dab36ecb97b89eccecd16eaad67258f1c7d9a36c731c74e3b78d47fe706e7cb8b8ca560a7cceace7b9e7d8a52d0e2d929053515a714c4550e549deecfcedd39db378dfce1ba671d9d984a38ba0771b0f88a333f39566d842345cb9fb30c21544574a336d063cd48f3be60339be147359e7e7e5d13a92ea90256bad0bfda4a2ad47c81de984855b705b6afaac6524ae9dec6bddcf1d374e3da46960d3cd1d43af7bfa711fe2d5d28de17366cd4e3b2a77ec472dbbb497a99f772d20e8ab7bc5e5adf88f05e213520f47b3df216a05ba2ef604a5be9964cd5af18b532d57642bee30c5db7cfd689656bfbe7e0d2d1aa0dded7ffb51e0ee9edf112faf6f63dd48a403e2e6f5edded658a095e81b99b3dea0d2a5dc11cdbd92754f7ede518540bd53b3ca12dd1a8f9c69cc666aea8ef6e8fc84f3f1e008014bd16c3507f188dc8ac92c8789416c90753eafa94f12cedfbef89069879019a8f18359a271a7ce8ebacf60fa7cd925b2f7baa9755b5b68155657789d7392f69e055ebb698d5d2a7f552d08ea11b99425b74138d9f251c7272c6d79274fdab3ff52d82a72602970774fad47c7d7165bc9f977a8a7cab495b9df1aa24d06c682fd18cac5c823209ad4c8aa9518e35ce755726b154553c2b3cb21d1a42a76ab31b1ab599486d26623a4f5690d6804c0a0d4f69f11227178928f04d9f79550ba145e40ba3cd6b601afd81d5a22904d545e5459a653c945fd3ec427d896692f410ef1ed7338707556f89941bf79c8147e8c115665b34c5e6c67c7b559f34042c0288c87e67b5e25eaf36de1a6079099b58de65f48828a7c722fb2db9a671582bd05ab50d363208b80ccd12867764faf3d3dce472509aa10e046d57140f48eb3d4785e529393cf8e13fe4a1f9c7a9d525e4e4c8033af551edd6d20f43bc091b90df93dbb0d687a77b30f3b21f339d5cdc83fc0b3f79f38e23cfc0d8953fe09a60979fad28be3efe15f999bc006afce9d06613f43e7e761bcefab0741f37ebc54b2713f7a07ef9199cac5842cab9a38f59cc7b6fdab4108dd2ab685dbcaade4efefcfeedbd316db2bf8be3f9b2649727cf3e31b33e5607c6252a79f91a2a53cca34acb2b7c99279c8c6f0e473f6d2617cd765d02ef44ab8724b0ee5af6eb53eea606625972251f691864b2ed51e7735d9a303d44fd1318d0161f072363589e52eb7f63a31e163c62c53c2d63674616f48f9baf6ea8fb3f80fb487f35486c0cb47405e404becafc4459014bf2a301deea1f1076b12fefaa1f0dece6ee4ce31c43913678fa6422573ed5145c4731d454b2e4af529ec0184aead2d15f252cc6d7f52f5e2227861469c22e1f6f7148358c084d57231209c1a1be9b0b9e369d1ec7c60fc0bc0534fee39215cb6421eaca37fc98d0abf751ea3f99936f50f439f3a93e9309b9a204c24899c62c10aa88026d7b811567a0d9f708958875435bf2bc70ea2cd5f796b7bca973a45a90f30ee6c4529d10128a8214244a398de2f59dd8938748edfcede621298842f849b5e38c681fabf5d3384a755f4456eefc7f000000ffff010000ffff0689b81c14470000") gr, _ = gzip.NewReader(bytes.NewBuffer(bs)) bs, _ = ioutil.ReadAll(gr) Assets["app.js"] = bs @@ -63,7 +63,7 @@ func init() { bs, _ = ioutil.ReadAll(gr) Assets["favicon.png"] = bs - bs, _ = hex.DecodeString("1f8b080000096e8800ffec5c6d73db3892fe9e5f81b0ee26499d49d97999db72645565eccc8e6b6792549cdcded5d67e804848c4980438006847ebf1fdf6eb06f82e52966429f1dece075b24013480c683ee076083e3c767ef4f3ffdcf87b7243669327934c61f9250313ff198f08898fb34cb4e3cbd10a189b998db47a11446c92461eac4bb28534e8d4a3c122654eb130f3325925e7a2892d168f2889071ca0c25614c9566e6c4cbcdccff935727c4c6643efb2de75727de7ffb9fdff8a732cda8e1d3848158a891092875fef6844573d6282768ca4ebc2bceae33a94c23eb358f4c7c12b12b1e32dfde1c102eb8e134f17548137672141c2e098a980e15cf0c97a2216b291bcd4d2cd5528e848b4ba258021a836413e686f01025c58acd4ebc19bdc2db2003454e1e6101c34dc2269512c9efe4e606aef43b19b17750d3d367b7b7e391cb5555e0844da534da289a8d42ad47d55d907211c013af688759244cc78c19d7427b4fcc22834e18f6c560619b42c854460b72632f09c968144183fca93446a6c7e43f0fb32faf8bb41974da9fd194278b63e2fdc4922b667848c93b9633ef80540f0ec81b05da3e209a0aed6ba6f8cc89b87d647fe2a303123f87bf17f0f712fe5ec1dff75513ee5d4d21e29af1796c8ec98bc3c356f534981a51d586caf023164a4571f08f899082b5f2e7c97fc4afaafc2955732e7c23b3637214bc62692b6f60c5a552489dd190f5f7a94aee14a580799c6411139a4513636790511344f0722a0edb70ea0c70319c5a498e564aee4dad244755efa652454c399d2ca9cf56468c828bb6d269c2e7a0ef10e611536d5524722e3b1a3f2687afdb186d3cb135fbaf6aa8665273379c301b6060af3abace949c2ba67555495c80e5f9512da418ea722a701103c6cc80a0eaca9f5255898579cbfc3ed916109aff83018a9e978f4ba12118599a81b6fd2baed11256f222aeb3842eda6a6e9759ab3817d8b28ed2b936be90fe3407136f1a5d80c7d67cf8683e5cd59d82808f244fc5503dfe3491e165a556d0a9b5cb605dcae953295b39551dd509531a5ece95cc4584b54805433a9f3e7dfee2fb03f2fce521fe3b7af6ba0d4445239e6b98f90d4094988131202fbb630c63038f1be3d0e917cc56114414dc40c70c246c06ad3daced40ab7b4787f5e326e46d275fdfadab52c1a55bed870179cc53f4815474b029e81560d1c79afbcdd7cb6687c7233bc8e0b947ce753f1a5b4360fdd563df279f644610dbbeef9e81f8caefdb9a485921642c2e2336a37902ee197803b3f9f8dcdad9c2f78c235e09419f4a4103aa4843af057a6fd7e14f1515913719f3745ea6a0b5f0885621ba3d1feffca3e77fb2de963836e0bd78ee1553dc5d8f26a472be639dd224990cf8609708bfd094aa5d8d5617cdb2435a373ceb24e31878c4faf313ef134f199133e05bda58264143030d05fb885867b67b45b5560176f8adb49b27cebfe486454f8ea147549929a3869c9c90c3db8a86cd93451623e320d5956ff37a6547a0ab58fbe70c400d26e37782bfc74f7efae9384d9f34bb9d555d9ae66006454121dc4d55213a54f8f333c501600b7badd3120470e7f863c2c34b2098113717cc1850bd7efacc9bb446b9afe9a19cd70d2f4b8e47ae0d55fb46302805a8cacbf1085ae0c03a8033971fd1fd2357301a4a5e1f102992050122772d089f11c142b0ead0abd7e423d306b448aea912c8da8a995088871e72e0678f41fe8ccfcf0502acd21008f6fae00306c64f23c06b95da4e873eb384d8ff7e516d23674f5e1ce8c8e61ac72fda29167edea4ecc53bc62216c16c7f3169286f482cda8256cd88f2c9a79811d7dfdcf12712534da68c81cda457802c182430528600c4f915622da8271e49735479d11c23ab4cc81940efd76dd141038d9d111f6a347295863dd900c9805efc29ec17c9c0271673bc81e4a2e96b8118b83b648f6b2057c320afbb58ee814902d377c6bf783d43d57ed0ba5d9e144b8067f33c01d30df8ecc0b905dc521e16fcc82cbb9230cf911b90a768efd1113eab25f482fcfb35305e3a8c7b63bc682367fa3e08cf93cac9200dca85f5919105816219985e444126c17913fcfd1972211c5a52ecfaadfba8e3dddaeb066f727383e28233ae5888aab636b9e182ba620ae39382ef4afe668b9e9ffd3de0e20a284754a13ba15386ebfc296a1a56fb38376e6efa0bada8b1a3958a332ef57bb0efdd11a8a856e5241b283b3feb153ca043f48da46f061a5abb9175c421dfab06e2fc6c581fb664175f5bf413775b622505ff8733a5601f4cae77d2f750a629acb336ef7f837ca01e4ef1f269a19167a5762e6c43abc75b6a6a3cea47ca9600fa7322a734b1b3b2d0ef8c276c37ea9c836cb615983a736d6e1bf923360c48184daee942bfcbd32953b7b7aebd0764a0d00f0b630b4db9a0681f7ed80b3c7f96e1be9418cb74273a4cb0891baad096d98d06770cdbcfa23603a0b8dda91b569079e447c06a612919ed42f10208e4867ac722fb05ee6eace5369e624c8b1ddaee62074dbc358eebf0c48c899027354d7c0b02c623bab2391b62733cca932586b294b39b6b2f74bbe6d5a49f79377549a3c8aa722d3526e8394b25be89a2066ddd37dd6e9265dc4c68d064dbd507c493b1799b12e4b6d6e257930f8c29524a7ab505831650f6743647122d61e9a7acac1dd16851eee61495ac60275f85d75a40009271ab7827c60a5f0d6d65cd51213031d41a9ab132b6a510b6c70f90dbba2d59a707c76b6b4594fa2998ed3d35b4638a7056f870a2a8610f851b8018014b55185bfdb7425d018ebc5b514e33f4f829338a87b7b770b717a47dcef6a1963cdb8b52646e76a3951da3cb4ed72ba674bd4b7f3f2d6ebbee4685fd17db9b797a804411555f75f79f8f2b2e11834f31d79618dc9f17942f66fe9fb282d35c29f061e4e39b5f486e7852b8c9ddccbf78abe9a717dab034809fe65a0d5bb817db5d6ae0f4c3e7a606c8d3a343a297077d2b45507da9efa38b30cb3f3085010b9d152fdc0a200a8a26c747b7b7ff8e9d7808a6bc451470016268b21b55ee80307c0352b00715dc831c7c630250bc3128a00d7d7d2384cc45c8deff853c3e21b980252617acf1f260688b9516058966ea6a69fdbf9d76d1c4c652892d59bdce437c6bebadeaa537796f232eb6aaa0787b52bdf41da86036bbab863f78cb37e72d2b2af9167b5c25cdd9628fcb71adafb0bbe5aedd16d7a8fdee181fbd554a2add1f1fc130cdbd270d1226e626261372f8100325de49c34376af0089269b858e23936df4bf8af3b9b981a7818d0b2a42713c8cc439060b767b7b5c46e3909b9b99e24c44c9c2ed906121ab6a4b5ff71f1cb111922dca1c10b0a7effff275a31c5a08ad427eaae0357cfc830dec5c2fa6ad0c04296ea1912c2a224349cca38809ff8b5e2fa8ad37360c2050acb95b43d9587c60d38a128dcb76dc99f3f960a7db35d82dc2c27663bcfdf10894a343992bcd822ac63f10cc8cbcc9459e61342119911fa5ca5367979b8673b08a52113a6d56a6a1b63937713e0d42998e429aa4f1a8aa74a4180cbac6775c3f03ee352c81dc830dea5db36b21c89f4bb5184532cc71c7b058629d356ff7dd5dae758e9dfd21c710b6bdd60543096a005a766abd42bbaedaf3f545cbd93717cc5c4b75e9ec154965044caf9c2608701e410b5d1e3bcb2b2be1b2ce68c47ae6834df4234e1339efb5f32e4371be62c0d6bb3c68bf6146d384015aedff2aa6a56938e297ed6285716f1ba1bb5c2dfb0289a94588aff97c80969e56db7dce03b6ec57fc72c07cf5f56dc9998cb3765575109d662cd5183d3765041764074462ac3d538c704d28c9949c262c7501a60b400439c7807b183a526f4f062de11f6141b200d9dfc52c4978f6bad58f6c6d2bdc32c72e72cc86bcd9d0bf5e3ca92ac34340131733b9072c7523013baa2f35f055c00308a9751e900fd6f4925826d1aec7de6e2be36261d098942b89cd87de09f493dd60a0adba557c284ca486e6e2ea085aa2535e89f208559cface6ac3724ce5d087ef0c103cfdba8f0721b2803a61d0312c265113301e6fbf004b5c9a0b25e86abedf044747d45a9270f9d5236a0b9ccda44a8b507fbcf48a5373b8347c6b87be3b571a32b1808f073d32af15f11e53ed5b1ff4048f3b948202615fa304ff56442b92efbeeb4b8db8328bdb9e2d631b080955bac66184a105e8f91938494c5b2ac14586a1ccc5727f49af75474196f38dc575b37bc5094aaf7110cf76d646c9009edc1e28b6a4784d84a7f97ecbb96211580bdb84a58635975603a37d0d5399e03fe40ff85a6aa91e587684712e2e5d9863cf4abb66ad6017327748a5672ba2158cda331e6eac7effbd6fac32659b0d80c4a872e186031d9b3d2046ac470b413af8b9191e0772af0518f1ca990033d19903e9126c2c811514900bdcf90777885e712e242834582ba0b6a79d168c41392eab80d7ee4988fb64069b3f4da8b81ca8bfb38eebddf81898362b514e31d80e5f79ac067896809ed0fee321df9f242c482fdca69ec3344ad91ad1d4c5fbf5c3b8175f17ee1086d006cf10ca1929266939f461926bc4868b26e81e10d895ee8a680da4ed6fcacb0db4182d406d3cb46a012f81e729a3beb98e8778d245693eea4ab7d577d5d60ba336d4fb5b3be330b08202bfcca8b2a78456be53e3d9312e1bcbdda8aaf9c84657162cd4531684f99e31651d09cd61750d9c3b24764907285c200670e00bf16b8cf87884b2967642869d6d5bde5f6326883b3b085c1acfa4e0743e20978c6588c294832132313564ccd209bea5b419c623b873e75ba6b6b5a0be9655d21c806ca40c089a8812d6b6778508e066c79ddd24c5300873d135d7f87ccdad923e37deb30fb4c961afe69e0f9ef929b62fdb686f58c8d263c3ec86dcbd64689ddaab1da73ef635394566b64a76bfc744635e02e2822533ef8e36d8e5a63b1c8407609aaa80e9c84ca98cc999bd5b6ed0e62ba84cdecda231d71f2c7a6d16dd8c0cdd09971e12b83b468dd1c43b61d4b5a0002f3b8cba27750d46edb2360e612deee6d555afd0ffb5dd67b13da73b26656938dc068293b0b9cbfce842d46bc24d72c17fcb196edfcbcdbc673753934ff668b4e2c43d693527bec00f8b401fa1a97cc6c1eaccdc364fe36c46407e291c0e3ed7144f1983f34a928a27a119d643c4f38e663adaeb94620d8c25b7aa39c695c373b9ee5551935f0fc1b0af097b67d9eb4ea50fd4c4ab26934b5f733a61e6d684c207eb4e295bb83da9fe7774564fab72e2b87c5b4e9deaa4e21a4bd6fbce1aa7baa179e352eb9983f7482bdb93a5a463f62410525d68285301f92b87f902e80915b3a497cf0858f448326dcf313334375b00db35ea4e683740b104ee0cfbf1f51791cd9759310b2fa7f24bdfc2bf178a0d383a0455120650f411b8c37b9140e79bc78c7fa168bd96eb1cc0fffafb17eef4126e0a640a487088033e5332c5cf5501b5d324052a8348a9b712f4813dd3decd50b27f47fc2d7fbf2e90a4315eacc21f18c8620d5318e57dad5a6d63ab131efd9aea1bdb6e00e69da7327636f81a48320e81adc8c64b97c1d21ebefb6ec56c3ebbbddd031e2e6c0bdce707b011386c3a467cd865596332e2db946fb1faac9bd0b706c586b758176ef0e7f85120c41f6f98136e3b376716d75366aef1930d8e1ee08a74612745882f0300bef82da52b58c64235d6c3c3a23c8cc114d2d0248baa34120d27e1e12c468bf3626de6d8b0b90f79317aefc56779586e578bcff2d32b032b4f5d24ffabae3cfb96838dcfd5ec782138ec1f9a11547de93da70cfbb275286fe9128a5146bb530d78afe56fc698ba8c010e02ee72daaf183d41eab694226c3cf5938128c7a67fbbb9290be3b72a6c9476716fbfe5881b63836ea9724c88db8ea05504b8ce8af798b9e1c9ecb76a82f7993bee53cbfcfbe0e66b0f140686ace9397b353a953259adb5fe344296f4b64a372b1cf976dd1ff4da2b74d3efd07b1fee03f6f39c5fec0ff9bd691934ed5aaae89f785efcf9f3f9bfea9cd8a4ebfb9c0f77b2d3afcdce9a5f81fbfafc6b6dfa8397eeebc0ee238340bcf09b59f68bbbbfba086c9b3ae966fcf5b79ca985ff3c380c5edc9dbbfeb0efafddeffaae2c47b3ac9301fa6abfdc08a4c37edef9ff000000ffff010000ffff877de943ef590000") + bs, _ = hex.DecodeString("1f8b080000096e8800ffec5c6d73db3892fe9e5f81b0ee26499d49d97999db72645565eccc8e6b6792549cdcded5d67e804848c4980438006847ebf1fdf6eb06f82e52966429f1dece075b24013480c683ee076083e3c767ef4f3ffdcf87b7243669327934c61f9250313ff198f08898fb34cb4e3cbd10a189b998db47a11446c92461eac4bb28534e8d4a3c122654eb130f3325925e7a2892d168f2889071ca0c25614c9566e6c4cbcdccff935727c4c6643efb2de75727de7ffb9fdff8a732cda8e1d3848158a891092875fef6844573d6282768ca4ebc2bceae33a94c23eb358f4c7c12b12b1e32dfde1c102eb8e134f17548137672141c2e098a980e15cf0c97a2216b291bcd4d2cd5528e848b4ba258021a836413e686f01025c58acd4ebc19bdc2db2003454e1e6101c34dc2269512c9efe4e606aef43b19b17750d3d367b7b7e391cb5555e0844da534da289a8d42ad47d55d907211c013af688759244cc78c19d7427b4fcc22834e18f6c560619b42c854460b72632f09c968144183fca93446a6c7e43f0fb32faf8bb41974da9fd194278b63e2fdc4922b667848c93b9633ef80540f0ec81b05da3e209a0aed6ba6f8cc89b87d647fe2a303123f87bf17f0f712fe5ec1dff75513ee5d4d21e29af1796c8ec98bc3c356f534981a51d586caf023164a4571f08f899082b5f2e7c97fc4afaafc2955732e7c23b3637214bc62692b6f60c5a552489dd190f5f7a94aee14a580799c6411139a4513636790511344f0722a0edb70ea0c70319c5a498e564aee4dad244755efa652454c399d2ca9cf56468c828bb6d269c2e7a0ef10e611536d5524722e3b1a3f2687afdb186d3cb135fbaf6aa8665273379c301b6060af3abace949c2ba67555495c80e5f9512da418ea722a701103c6cc80a0eaca9f5255898579cbfc3ed916109aff83018a9e978f4ba12118599a81b6fd2baed11256f222aeb3842eda6a6e9759ab3817d8b28ed2b936be90fe3407136f1a5d80c7d67cf8683e5cd59d82808f244fc5503dfe3491e165a556d0a9b5cb605dcae953295b39551dd509531a5ece95cc4584b54805433a9f3e7dfee2fb03f2fce521fe3b7af6ba0d4445239e6b98f90d4094988131202fbb630c63038f1be3d0e917cc56114414dc40c70c246c06ad3daced40ab7b4787f5e326e46d275fdfadab52c1a55bed870179cc53f4815474b029e81560d1c79afbcdd7cb6687c7233bc8e0b947ce753f1a5b4360fdd563df279f644610dbbeef9e81f8caefdb9a485921642c2e2336a37902ee197803b3f9f8dcdad9c2f78c235e09419f4a4103aa4843af057a6fd7e14f1515913719f3745ea6a0b5f0885621ba3d1feffca3e77fb2de963836e0bd78ee1553dc5d8f26a472be639dd224990cf8609708bfd094aa5d8d5617cdb2435a373ceb24e31878c4faf313ef134f199133e05bda58264143030d05fb885867b67b45b5560176f8adb49b27cebfe486454f8ea147549929a3869c9c90c3db8a86cd93451623e320d5956ff37a6547a0ab58fbe70c400d26e37782bfc74f7efae9384d9f34bb9d555d9ae66006454121dc4d55213a54f8f333c501600b7badd3120470e7f863c2c34b2098113717cc1850bd7efacc9bb446b9afe9a19cd70d2f4b8e47ae0d55fb46302805a8cacbf1085ae0c03a8033971fd1fd2357301a4a5e1f102992050122772d089f11c142b0ead0abd7e423d306b448aea912c8da8a995088871e72e0678f41fe8ccfcf0502acd21008f6fae00306c64f23c06b95da4e873eb384d8ff7e516d23674f5e1ce8c8e61ac72fda29167edea4ecc53bc62216c16c7f3169286f482cda8256cd88f2c9a79811d7dfdcf12712534da68c81cda457802c182430528600c4f915622da8271e49735479d11c23ab4cc81940efd76dd141038d9d111f6a347295863dd900c9805efc29ec17c9c0271673bc81e4a2e96b8118b83b648f6b2057c320afbb58ee814902d377c6bf783d43d57ed0ba5d9e144b8067f33c01d30df8ecc0b905dc521e16fcc82cbb9230cf911b90a768efd1113eab25f482fcfb35305e3a8c7b63bc682367fa3e08cf93cac9200dca85f5919105816219985e444126c17913fcfd1972211c5a52ecfaadfba8e3dddaeb066f727383e28233ae5888aab636b9e182ba620ae39382ef4afe668b9e9ffd3de0e20a284754a13ba15386ebfc296a1a56fb38376e6efa0bada8b1a3958a332ef57bb0efdd11a8a856e5241b283b3feb153ca043f48da46f061a5abb9175c421dfab06e2fc6c581fb664175f5bf413775b622505ff8733a5601f4cae77d2f750a629acb336ef7f837ca01e4ef1f269a19167a5762e6c43abc75b6a6a3cea47ca9600fa7322a734b1b3b2d0ef8c276c37ea9c836cb615983a736d6e1bf923360c48184daee942bfcbd32953b7b7aebd0764a0d00f0b630b4db9a0681f7ed80b3c7f96e1be9418cb74273a4cb0891baad096d98d06770cdbcfa23603a0b8dda91b569079e447c06a612919ed42f10208e4867ac722fb05ee6eace5369e624c8b1ddaee62074dbc358eebf0c48c899027354d7c0b02c623bab2391b62733cca932586b294b39b6b2f74bbe6d5a49f79377549a3c8aa722d3526e8394b25be89a2066ddd37dd6e9265dc4c68d064dbd507c493b1799b12e4b6d6e257930f8c29524a7ab505831650f6743647122d61e9a7acac1dd16851eee61495ac60275f85d75a40009271ab7827c60a5f0d6d65cd51213031d41a9ab132b6a510b6c70f90dbba2d59a707c76b6b4594fa2998ed3d35b4638a7056f870a2a8610f851b8018014b55185bfdb7425d018ebc5b514e33f4f829338a87b7b770b717a47dcef6a1963cdb8b52646e76a3951da3cb4ed72ba674bd4b7f3f2d6ebbee4685fd17db9b797a804411555f75f79f8f2b2e11834f31d79618dc9f17942f66fe9fb282d35c29f061e4e39b5f486e7852b8c9ddccbf78abe9a717dab034809fe65a0d5bb817db5d6ae0f4c3e7a606c8d3a343a297077d2b45507da9efa38b30cb3f3085010b9d152fdc0a200a8a26c747b7b7ff8e9d7808a6bc451470016268b21b55ee80307c0352b00715dc831c7c630250bc3128a00d7d7d2384cc45c8deff853c3e21b980252617acf1f260688b9516058966ea6a69fdbf9d76d1c4c652892d59bdce437c6bebadeaa537796f232eb6aaa0787b52bdf41da86036bbab863f78cb37e72d2b2af9167b5c25cdd9628fcb71adafb0bbe5aedd16d7a8fdee181fbd554a2add1f1fc130cdbd270d1226e626261372f8100325de49c34376af0089269b858e23936df4bf8af3b9b981a7818d0b2a42713c8cc439060b767b7b5c46e3909b9b99e24c44c9c2ed906121ab6a4b5ff71f1cb111922dca1c10b0a7effff275a31c5a08ad427eaae0357cfc830dec5c2fa6ad0c04296ea1912c2a224349cca38809ff8b5e2fa8ad37360c2050acb95b43d9587c60d38a128dcb76dc99f3f960a7db35d82dc2c27663bcfdf10894a343992bcd822ac63f10cc8cbcc9459e61342119911fa5ca5367979b8673b08a52113a6d56a6a1b63937713e0d42998e429aa4f1a8aa74a4180cbac6775c3f03ee352c81dc830dea5db36b21c89f4bb5184532cc71c7b058629d356ff7dd5dae758e9dfd21c710b6bdd60543096a005a766abd42bbaedaf3f545cbd93717cc5c4b75e9ec154965044caf9c2608701e410b5d1e3bcb2b2be1b2ce68c47ae6834df4234e1339efb5f32e4371be62c0d6bb3c68bf6146d384015aedff2aa6a56938e297ed6285716f1ba1bb5c2dfb0289a94588aff97c80969e56db7dce03b6ec57fc72c07cf5f56dc9998cb3765575109d662cd5183d3765041764074462ac3d538c704d28c9949c262c7501a60b400439c7807b183a526f4f062de11f6141b200d9dfc52c4978f6bad58f6c6d2bdc32c72e72cc86bcd9d0bf5e3ca92ac34340131733b9072c7523013baa2f35f055c00308a9751e900fd6f4925826d1aec7de6e2be36261d098942b89cd87de09f493dd60a0adba557c284ca486e6e2ea085aa2535e89f208559cface6ac3724ce5d087ef0c103cfdba8f0721b2803a61d0312c265113301e6fbf004b5c9a0b25e86abedf044747d45a9270f9d5236a0b9ccda44a8b507fbcf48a5373b8347c6b87be3b571a32b1808f073d32af15f11e53ed5b1ff4048f3b948202615fa304ff56442b92efbeeb4b8db8328bdb9e2d631b080955bac66184a105e8f91938494c5b2ac14586a1ccc5727f49af75474196f38dc575b37bc5094ad2d9906e9ccbb37db74133002fb7258a0d2bde1ae1e1bedf72ae5804c6c3b668a99dcd95d6c0e05fc3cc26f80fd9fbf2def872b5b02809e35c5cba20c89e7578cd69c16a64ee084bcf46452b54b567b4dc48fefe7bdf4866caf6025a8831e7c20d16ba3d7b7c8c587f178274f082333c2ce45e1a30e295f304e6a93316d225d848032b282017d8777096502ca23ac64b1027ed715030414fc1e34b50fab360ad20dc9ed65b0007e5e0ad026bbb7f21eead19ecd434a1e272a0fecedaaf77b36460aaad9c191403f4f035c9ea499125a03df4197830f827098bd80bb711e8e6014ae99b056bc19eba18c17eacf7a2eec21ddc10dae0b9433923c5c42e011126b946c4b80884eea1825de9ae88f040aaffa6bcdc408bd102d4c643ab16f02c780633ea330878f0275d9426a7ae745b7d576dbd306a43bdbfb5f31083312870d28c2a7bb268e57b389e1de352b3dcc1aa9a8f0c7665c1423d6541b0021953d6f9d01c56e4c0d34362978180c205620007be10bfc6888f47286b69f764d841b7e5fd356682b8f386c0bff11c0b4ee70372c95886284c39d819135343c62c9de09b4d9b613c823b7726666a5b0bea6bd92acd01c846ca80a08928616d7b5788003e773c88dc3bcc3ec268a5a15fb505d3470f7af697363944d6dc4bc2b344c5b6687b4634ac68c904c00240ee5e92b54eedd54e561fab9b9c22e35b25bbdff5a2c12f4173c1929977471bec32d61d3ac283354d55c09465a654c6e4ccde2d3768f3955926ef66e798eb0f76be363b6f469cee84a30f09dc1d53c728e59d30f55a5080971da6de93ba065377591b87bb1677f3f5aa57e823db2eb6d8f6d31d93b2341c6e63c249d8dcad7e74a1ef357327b9e0bfe50c5f0bc8cd3c6c37539373f668b462d33d69359bbec00f96401fa1a97cc6c1eaccdcf651e3cc47407e299c123ed7144f2f83834b928a4ba119d643e4f48e663a6aec94620d8c25c0aa39c6955374b9ee555193830fc1b0af097b67e2eb4ea50fd4c4ab26934b5f733a61e6d684c207eb4e295bb83da9fe7774564fab72e2b87c5b4e9dea04e41a6bdffbce1aa7baa179e352eb9983f7483ddb93a5a46cf68411d26168285301f92b87f902e80915b3c498cf0858f448326dcf473334375b00db35ea4e683740b104ee0cfbf1f5179acd9764310b2fa7f24bdf96412f141b707408aa240ca0e8237087f72281ce378f2fff42d17a2dd73980fff5773edca928dc43c81490e010077ca6648a9fc1026aa7490a540691526f42e8037b56be9ba15c21b8c581e5f8d7059234c6a155f8030359ac730aa3bcaf95ad6d6c7572a45f537d63db0decbcf3b4c7ce065f0349c621b015d938ec3208dbc377eaad58d067b7b77bc0c3856d81fbac013602874dc7880fbb746b4c467c4bf32d56a87513fad6a9d8f016ebc21707397e6c08f1c71be684dbcecd99c5f594996bfc1484a307b86a5dd84911e24b06802f7ea3e98ad96d37ebe161e11ec6600a69689245551a898693f07016a3c539b436736cd8dc87bc18bdf7e2b33c84b7abc567f949978195a72e92ff55579e7dcbc1c6677076bc101cf60fcdc8acbef49ed38b7dd93a94b77409c528a3dda906bcd7f23763575dc60007017742edd7919e20755b4a11364efbc940f464d3bfdddc9485f11b1836fabbb8b7df88c48db141b7543926c46d47d02a025c67c57bccdcf064f61b38c1fbcc1d23aa65fe7d7083b6070a0343d6f49cbd1a9d4a99acd65a7f1a214b7a5ba59b158e7cbbee0f7aed15bae977e8bd0ff701fb79ce2ff687fcdeb40c9a762d55f44f3c2ffefcf9fc5f754e6cd2f57dce873bd9e9d76667cdafcb7d7dfeb536fdc14bf7d561f7f142205ef82d2efb25df5f5d64b74d9d7433fefa5bced4c27f1e1c062feece5d7f30f8d7eef7825796a359d6c9007db55f8404d2613f1bfd7f000000ffff010000ffff954a9464475a0000") gr, _ = gzip.NewReader(bytes.NewBuffer(bs)) bs, _ = ioutil.ReadAll(gr) Assets["index.html"] = bs diff --git a/config/config.go b/config/config.go index ff34b3def..e5f601f74 100644 --- a/config/config.go +++ b/config/config.go @@ -9,6 +9,7 @@ import ( "reflect" "sort" "strconv" + "strings" "code.google.com/p/go.crypto/bcrypt" "github.com/calmh/syncthing/logger" @@ -181,6 +182,14 @@ func Load(rd io.Reader, myID string) (Configuration, error) { cfg.Repositories = []RepositoryConfiguration{} } + // Sanitize node IDs + for i := range cfg.Nodes { + node := &cfg.Nodes[i] + // Strip spaces and dashes + node.NodeID = strings.Replace(node.NodeID, "-", "", -1) + node.NodeID = strings.Replace(node.NodeID, " ", "", -1) + } + // Check for missing, bad or duplicate repository ID:s var seenRepos = map[string]*RepositoryConfiguration{} var uniqueCounter int @@ -196,6 +205,13 @@ func Load(rd io.Reader, myID string) (Configuration, error) { repo.ID = "default" } + for i := range repo.Nodes { + node := &repo.Nodes[i] + // Strip spaces and dashes + node.NodeID = strings.Replace(node.NodeID, "-", "", -1) + node.NodeID = strings.Replace(node.NodeID, " ", "", -1) + } + if seen, ok := seenRepos[repo.ID]; ok { l.Warnf("Multiple repositories with ID %q; disabling", repo.ID) diff --git a/config/config_test.go b/config/config_test.go index 70a7603ce..ece912f11 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -224,3 +224,53 @@ func TestNodeAddresses(t *testing.T) { t.Errorf("Nodes differ;\n E: %#v\n A: %#v", expected, cfg.Nodes) } } + +func TestStripNodeIs(t *testing.T) { + data := []byte(` + + +
dynamic
+
+ +
+
+ +
+
+ + + + + +
+`) + + expected := []NodeConfiguration{ + { + NodeID: "AAAABBBBCCCC", + Addresses: []string{"dynamic"}, + }, + { + NodeID: "AAAABBBBDDDD", + Addresses: []string{"dynamic"}, + }, + { + NodeID: "AAAABBBBEEEE", + Addresses: []string{"dynamic"}, + }, + } + + cfg, err := Load(bytes.NewReader(data), "n4") + if err != nil { + t.Error(err) + } + + for i := range expected { + if !reflect.DeepEqual(cfg.Nodes[i], expected[i]) { + t.Errorf("Nodes[%d] differ;\n E: %#v\n A: %#v", i, expected[i], cfg.Nodes[i]) + } + if cfg.Repositories[0].Nodes[i].NodeID != expected[i].NodeID { + t.Errorf("Repo nodes[%d] differ;\n E: %#v\n A: %#v", i, expected[i].NodeID, cfg.Repositories[0].Nodes[i].NodeID) + } + } +} diff --git a/gui/app.js b/gui/app.js index fa58db77f..44a85a150 100644 --- a/gui/app.js +++ b/gui/app.js @@ -460,7 +460,7 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) { $scope.init(); setInterval($scope.refresh, refreshInterval); - setInterval(heartbeat, 450); + setInterval(heartbeat, 650); }); function nodeCompare(a, b) { @@ -581,7 +581,7 @@ syncthing.filter('chunkID', function () { var parts = input.match(/.{1,6}/g); if (!parts) return ""; - return parts.join(' '); + return parts.join('-'); } }); diff --git a/gui/index.html b/gui/index.html index bda69f560..a1323e7d8 100644 --- a/gui/index.html +++ b/gui/index.html @@ -368,10 +368,10 @@
- -
{{currentNode.NodeID | chunkID}}
+ +
{{currentNode.NodeID | chunkID}}

- The node ID to enter here can be found in the "Add Node" dialog on the other node. Spaces are ignored. + The node ID to enter here can be found in the "Add Node" dialog on the other node. Spaces and dashes are optional (ignored). The node ID cannot be blank.

@@ -388,7 +388,7 @@
When adding a new node, keep in mind that this node must be added on the other side too. The Node ID of this node is: -
{{myID | chunkID}}
+
{{myID | chunkID}}