Archived
Anonymous Usage Reporting
This commit is contained in:
1 parent
7454670b0a
commit
f40f3b3b7b
7 files changed
+260
-13
No files matched your search
+2
-2
@@ -18,7 +18,7 @@ func init() {
|
||||
bs, _ = ioutil.ReadAll(gr)
|
||||
Assets["angular.min.js"] = bs
|
||||
|
||||
bs, _ = hex.DecodeString("1f8b080000096e8800ffec3c6b73db3892dffd2b30bacc929ac89493d99dbb8ae36c659cccae372f579c4c5d9dc757458990c531452a246859e5e8bf5f3700527852749cccee55adab6662038d7ea1d1e86e001c8fc971b15c97e9e59c91f078481e1f3cfa33f9477c554cc8cf457949e23c21059bd3924c8b9c95e9a466455945e47996113eaa2225ad68794d93680fb07dac28296684cdd38a54455d4e290c4c28813f2f8b6b5ae634219335a0256f4e3eec576c9d5192a5539ac338368f199942d78422aa595103f13487764a5e9f1cbf7c7bf692ccd28c467b7be31f7eafb234676452162b20ff84b0b2a623ce649ad7b4f97b99d515fe27fe263f8c61e465564ce28c3c784266715601509c5fd6595ccabf11682fa8e1970ae49db2e0706fef3a2e49b5cea720567e498e9a11d1a248ea8c8641db178cc8f9c5f0900fa8cb6c12039a2312808a389e162e024667e96538aba1212d72123e9833b63c2d8beb34a1e590dcee11f8d11aa384cee23a6355745395b3bfd318dadec60b4ee0bff78fcfdeffb2ffa1b8a23910da31f6b828ae52da8cd5466e86269bac2cb28c966170d6b41eb332034115deab69b1044572920defa8826549af5fc40cc91c1cb6ad9794bd7b054d3825db56d4515c32a1603e13c009178463475672ca09560070bb39343a419d76fb627df202650cb4d61c2c12919c5f38909ce428a8c69eec5f96052ba645763c87f9073b6ed954606859c2fab0715794e62fb1cfe6068c886636eb255d168da4bc1d96c41958647e59c1029915252593a2c82a92c16c420b63b4d42932c6818117de7e9b264f48f03aad18cd0111cc2068610a66cf67969c4ae9888020cf9304a6a4a21500b2f5129654c0e80d83bfe44c8935b51929c8dfc43767344f5e4d969582fe5dcd2e0b9cd7f7680aafd3450abee655faf3b81a6e71e7f56242cb4eecef015f9c9fe420e8759c9d2914440f69ba487867ccd2badcc865e797e33f8dcb181651f69e7eaa0148550ea88c808260649e701d6d41fae30724c2280dcd23f25fc06312d12b26a0bfea150a7fe34ef3799ebfcce34946138588e8222f52b03bf0f0eb2d62b4cf4ebe5f17530f52de732f9ca745c9fc0889eceeafe3336cff596c37eadac166b26d57d9d4c67f3ccd4f6d39450bc14ef7e00bdd0b5ed6e9997b61cbf5aa4eccc793fb2ce68fbaa088ed790d7b31ecb0d3983bfe8f9ac83b119ec655b52acaa41ba90225112fb72d9ddc7e78ad2e5b8c44fefee1c3e919041225014277b0a1e7a727afe85a41060d44b44814f132bd82bf8d496ab744d8e2ceeae994d2842661b323e24f3a23e1777c03545b95094ef39485c343bd2b0cfe23a70c7470c5f79060889b469c85c11c36f7c080b6b757fcd9682c6c37db3bb2b11dd8cd04c256f39a25c52aef8674edfb3ad31b5bb9bfc4e0d56ccdfac52a29abcbdca70ef784f8b47e3b89a75749592cc10e801e582ed80558c3a488cb4446911bcfa47409d86efc3390638ec06d84a5f2c6a3ac0810864d84f99004e36a0d0b7d013c56687755a5849649cc625338dd400f5d262030021b385e617928829cd0cd9d44de4c903a6efbfbbbc9efb09f46a0b32a54c39d61046bf5653c9d2bc8d3c49a18a7027818f5574473144003cd31eff8f8fee4b8582c8b1c1c0c62eaab1e450d1cef799a5c589a30a5527f77f3a8c4b0bd670a63e3bc5801758ca421765d85c39106c130140d1166bf8db887644c1e1d1c1ce89069221d55f3a304e8305e170ddd26e80c33309f8ab837c3ce681e57ef5639c4904b5ab23557b5031e7f9a14edd0eadd582d0c366a3716248a93028e0a421e60ff4dcce6d122be090f46e4bfc80f42971ce224ff79cd68f5a1601000ec3bd2090b0a95c792a1cda146b9a8d92ed210d8f5a1ad8179896f203766d33909a94fb596520efa8ae000d46763e3f2107a4a66ba895d8b41a44abdd7819960b9c96d0ef7cc240a223456579a3bc56673efc08dbd98e9ab1ee160dd1f41ce56e79042a739046feead05028efc2ac7dd4ef5ee1a051b354c14a413b0c6be43125ecc67ac582e81b21333af4d30b18603f47c0e32bc7f3bba01e7ff9e1f5c44acf80804ca63981a70e60f4507cccba46265f86878a8cb21871f9101268eb0d90ec8e7cf64db7a92647460ca22ba1f423709075b2eb1d4704acb29f8e7f892ca89794806df0f074e69a54a14811c337e9c41c4f8ed273ccd67c53798ed0453b5f2ab4db63663410a73e3a52c1762e00b93b6682a31f15e4ccb325dc490b6b93039d467cca16e14df7c22619ff449ec50af281f727fcdf11ff4c3aa4de172ca402a8080ddc26927b8b00489b10b40e1e1d0d42bdf8d665901111a9071bb452c8039dc22361fcfb4d819b945370f708ecd4b0e88dec2bf272f2e74a3434053374d7b8451594639595422a8c2b5a9b5ae754958c1e39fc008bf08c592ad7fa4f45024c4c56252865de8fba189b1c3eb04bc7cc0c56fbdb143b3275394eaff835e8babbbea5326277751da02a2bdcaaf2ddb59ffcbaacbf68fbd74663bc39d3af3fb469415ab397fb0c624635c69b298d4e5dbffda31df8acaff6922184ea0739ff28bf22bdd390dc88cce293734e578c2c3a684b8a66505b85dfc7d4bf56429ecbdbffa69ef9867d86e13246c694717172558604ec34f63d4c319c09031aad61890df866cbe552511580fb57c03459478a38ce6976c0e211779e491b88d0f3a0495d82056f61a833c4edb690d325a91bd3d4394c1c017a1b4f30ce43d8355900e19758b69a27fc8697f72071178c6fbd625b839c5b9b0046358684c98a297be4a096b9172f141c34e15edd24f1fe5f4d60c4d52a654e9dd9a198f2154bba224265861c41805c6aedb6eed4c329220ef964db2dd9c40e398508795406afeedc285a5f74e3c00a0e2c082ae94a96f2594d7d5dd2aaae26bd809e4a16da320cb72a6b840c83fcedebd8d2a7ef499ce0c2e150e7140b164fccc74ce4fc7ab27e436002a0c9cd9fe07b0af8057ee97993c6b18ff5e1579b0d998958a655159753ba005b20143234ec455b5e857a714b8c698e3f4ae7d5893d81e52f3e29bdab6bb3ce99889dec65ad525fcaf58507113622a4ec2f5396b4fc7bf6bad8b7eaae3ac72dbe9a8d3d487e4f3674b15e267077a305f0f6addb0d35928591eea4a07992b4ad1833407ff64956619c9294807e9c884b6b282bae4d1831166da3c45e2a08ad7007cdc4998a1d708ec9b08fa610f9fe63d539ae760f96b607f45dabb01199e8a66eb3dafa145bd5c8e3167871df876ba1de72479f98ac401a70c4989a9531dea8c955105ab9f85c1087d58bc54d6dd8d1260dc44e06d16b043f145e3e262ebbfb4338ebd6e7f39c003b081af54c90dc8bb04b573327dba3d0773773da7f2383f8939f06d28c68519d5679cad52ac58afe86489859c761dc19acaf9d1d39ebd540cdb1edaa7212d1a081290e5c098a28e65672f29139995dde9b8614a3fa40b5ad42cLine truncated
|
||||
bs, _ = hex.DecodeString("1f8b080000096e8800ffec3c7f73dbb692fffb53a0baf4897264ca49fa7a37519c4eeaa4eff9a5493c71d2bb39d79da144c8624d910a015ad6d8feeeb70b80144000141d2779ef669ea68d2562b1d85d2c16fb03e068440ef3e5ba48cee79c048703f278ffd10fe41fd1453e213fe7c53989b298e47c4e0b32cd335e249392e7050bc98b3425a217230565b4b8a471b803d83e324af219e1f384119697c59442c79812f8799e5fd222a33199ac012d7973f4618ff1754a499a4c6906fdf83ce2640a4d138aa86679098327193ca7e4d7a3c3576f4f5e915992d2706767b4fb274b938c934991af60f8a78417251d0a2293aca4d5ef655a32fc5ffe26bb23e8799ee69328250f9e92599432008ab2f3328d0af51b8176fa257c61c0ef94f7c73b3b975141d83a9b025bd93939a87a848b3c2e531af4ebb6fe909c9e0dc6a24359a49308d01c903e8848e0a9e1422074969c07b3121e247946820773ce97c7457e99c4b41890eb1d021fe36118d35954a69c8557ac98fd9d46f0ec6db41003fccfdee1c9fb5ff63ee417348381b6f43dccf38b84567d8d9eb7832699bcc8d3941641ffa47a7ac88b1418d56867d37c0982144356b4a3089605bd7c19711c667f5c3f3da7fcdd6b788453b2798a328a0a2e052c660228118c08ec484a46c5800c00ae6fc78d4610a7fd7cb13e7a893cf68da719682422393d732039ca9051833cd5be2c729e4ff3f4700ef30f7a5c93a9c1d0a280f561e3669466afb0cda6069488a636e9055de60e4ef171c141a891afed18849ed055438ab0a04e409fb37306cb6b9617944cf23c6524055d80279cd3c2a49773010c9c88e7d749fc94f47f4d18a7192082f907194e61d108bd20c74a3644429017710c13ca280340be5ec282ec737ac5fbb7430ddb9be8ea8466f1ebc99269f8de95fc3c4735788f9af36bb248c034bd4e7e1eb1c10659562e26b430d1bd0704517694012b97517aa2a1942da46a22c176544adddcd854e31d101e474504cb287d4f3f95a0e83abf2005023c83f667b1607b03d282107a493d6c480fb1fd024692c85629c416f1e9939b4fa3f445961d83126918c563f23201c50003be26aab985b60ad1ab2c9aa434f6e3daa041653491fc4d98692716d9d40dcd091a959fe52ea12b2d3e269be7defe1f8fb3639b02f98460636be7f776d717599ead1779c960af8c7082c4a2957b8703d1996905cfcbe4c4bd34d58ad3c5f4f168db721c5666576e9026f1a6c410db8b12f662d861a79130fc1f0dd96d45781c31b6ca8bb81da906a5102f374f5aa9fdf0abbe4ad113f9fb870fc727e0481404066ac8b70dd98be3a3d774ad4fdaf111914f148a68995cc0efc624d55b226c7127e5744a694ce3a0da11f193cc48f09dd800f5a7da042759c283c1d86c0afaff91510e32b8107b487f809b469406fd396ceefd06b4bdbde2e7d62061b3d9de918c4dc776221096cd4b1ee7abac1dd2b5ef9b44dfdac2fd250213674bd6cf56417959643e71b827c427f5eb4934bd888b7c097a00e381e6825e80364cf2a888951779eb99943606eb5d7c067ccc11b8f6b074da84971502c2a0f2301f92fe88ad61a12f8046867ac798e65ac6e02c3499331574ec52018911c8c0fe1ac903e9e4046eea14f26a82f47e9befef267fc2f61982cc58a0bb3b8310d6eaab683ad79027b135314e010837ea274473d0870734c3b8e3e3fba3c37cb1cc33303088a9ab78343108bca7497c6649a2c995fedd4da3e6c3769e29f48db31cdd39f4a4c1775d0583a101c1d1150d1066aff6b80764441eedefef9b9049ac0c55f5d11c74e86fb2866613648611984f44c29a6163388fd8bb55065ee092167c2d44ed80c74f15a28dadd65beb090777c38d0507c549014305fe0f90ff26e2f370115d05fb43f25f6457ca52401c653faf39651f720e3ec39e239cb0a050783c1ed8141a23e725df3634b8755dc636c0bc83df426ccca77312509f682da1ec7765c10168cec6adcb42982159d34c6c5b0c3254eabc0e9a01967bb8dbf14e332202578f97cc30a7f8b8b977e0c69ecfcc558f70b0ee0f20662b3308a1930c5c39f7d6020e477691e16ea75b7763041b354c14440fb0c6bec321bc984f78be5cc2c84ecc2237c1e51aeea3e5730c23da37bd2b70f1f774ff2ce4f94718a03884a90163fe5036c0bc4c182f824783b1c987ea7e407a18fac166db23373764f3f4284e69afc98b6c7e08cd24e86da8c454c3312da6609fc1195613f390f4be1ff49cdc2a91680c3966fc30058ff1eb4f7892cdf2af30db31c66dc5179b6c63c6fa09cc8d7764b510fb3e37698386c989f7625a16c92282c0cc85c921bec61c9a4af1d52712f6491fc70ef1caf4a1b0d702ff7e37acc6142ea71cb80208d82d9c7a820b4b0e31720168348c9b7215bbd12ccdc1438361dc661113600eb3888f0f6786ef8cd4a2990738c7e6a53a846fe1efd1cb3353e910b0299bea79885e594ac5b0284410856b53ab4deb92f05cf83ffd86fb4528a66cfd3d958522012e96e6c8b00b7d3f68626cb13a7d917110ecd7d6d821d9a32972f5ff41aef9c55de5a98293bb086d01de1ef34bcb36d6ffb2e2b2ed632799d9c670abccfcb61179c56cce379698224c084d2593da6cfb4f2df3ad89fc9fc642c308b4ee537e567ea35ba701893129158aa695273c642a884b5a30c0eda2ef6b8a274d60effdcd3ff6967986ed36c6812de998ec22070b8c694435462fce008694533dc780f456c3661b511289756cc41bc8a2c21ba6343be77370b9c8230fc7b57fd0c2a8c206beb2571954396dab36286f45b57674517a3d9f8752cf330cefe9ac83b4f0686a4ce5fd434cfba3db89c01aef5b17e3cd29cea42634ba058d09d3e4d255284129432ed169d02aa26df2e9229cce92a171c2b52cbd5b32a311b86a17944404338ce8a340df75dd6cd4244305f26e5905db55051afb0426ac02d2e36f172e4cbdb7e201001d072674154f5d33a122afee16118b2e61275045db4a4096e64c7181907f9cbc7b1b3251bc4c660d2a350ab143bee4a2663a17d571f6945cf761140ec66cef03e8575f64ee97a9aa358cfe6479d6bfbd6d662a9639b3f2763016f006040dc520aeac45b73ca5c435c218a773eec39ac4ba482d926ffab3ede949c74c7456565616f04fbea0f224c45456c2cd39ababe3dfd5da453f9551cadc7a3a6c55f501b9b9b144213f5bd083fa7a509b8a9dcc0245f2c0143af0cc28450b5215fec92a49539251e00ec29109ad790571a9d243c3cdb4690a65a14ae4007cd42998815709ec930866b1474cf34e939b17a0f96b207f45eaea7e8af5d874bde355b4b093c969ccd9b805df56b3e39c242f5da12c702a979434656a429df02264b0fa79d01fa20d8b96dababbd21c8cab10accd027628b1685c546cec9751e3d869b7973d2c80f57ca94aa140de2568d4c9cce9f614e6ee5aa7f2183f85b9efdb501a0766749b71b24a3063bda293252672ea75046bLine truncated
|
||||
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("1f8b080000096e8800ffec5d7b77dbb692ffdf9f02e1ed2676d7a4ec244dbb8eacb3ae9db6de368f1327dbedf674f7402424a2260986006deb3abe9ffdce007c3f245ab613dfb67f2416096030180c06bf193c387e70f4faf0dd2f6f5e105f85c16463fcc0b6370e45bc48f8dc5764f3708b3cded97d4afe8b9e8a29f956247342238f08e5b384b82252099fa64a24d22107414074294912265972c63c67e3bd6444cc88f2b92452a489cba094c7083ccec5194b22e691e902689297c7ef6ca916012301775904e5944f15712169ca366622856a79042f19f9e9f8f0c5ab931764c603e66cd836b08ddc938046f37d8b451689e6368de37d4b2e2217ea8ee6fa95e65704014bf6ad933ce550258145dc804ab96f61a640d0530b4932ea4d360819874c51e2fa34914ced5ba99ad9df586582af546cb30f293fdbb7fec77e7f601f8a30a68a4f03666909b1084a1dbfd867de9c55ca453464fbd61967e7b1485425eb39f794bfefb1331083ad1fb6a1e15c711ad8d2a501dbdf75765a843c26dd84c78a8ba842ab958da6ca17492b47c0a353e8b5002406c9ca4d15e12e52f21336dbb766f40c1f9d180439d9c0028aab804d0a21928fe4f2123bf91574ee2ba86973ebea6a3c32b98a0a0cb1a9104aaa84c62357ca51f1e4843c72e08d95f181aa207dc694e1d0a8865ac4d008c52e1416d629844c85b72097fa272131f53c60c89e0aa544b847bede892f9e67693368b43da3210f167bc4fa8105674c719792572c65d636295e6c938304a4bd4d248da40daacc6786c4d586fe9306ffee7f55d418d264ce235b89788fec3a5fb1b096d74166ed504442c614b4ffb28b97972c0ac436792922eac2df431149010ab94dac4318331c86da2b760e1c16641a55505036d46e0fc78d37515a75553241d569a7a2bcfa5367d021fda905656f29e5ced482b25748612a128f25467691881aed0ac45c34c4bc47769ed77bbaf24693b1bf2a3b3c1692e388d8439d823179d6ac804b6547c29ea660145451957ead15ce468533ac350a42c382348c8a321e977140a12f7904baceec6920dcd39c0f506d3392411f73fd281447db4c509d32614addd37982160f6b1109b03f9f6e3e7ef26c9b3c7eba83ffed6e3daf4b30a11e4fe51e7952697c2e9fddf8823c2ddfe7827c0caf1fe7afaf9aed02358b1c8f82e168e879c066c0ed4ea9e8b5e6edee94afb5e6d380cf51fed8c8e7ab65950b3837c46df9625f90073c44ab4923d53112608e288a9dfb5c315b8f99bd489c839da91983736684ff7467a79390d7b22ba6f98fc1aaf431f19f21f338259b21bdc8a4f2f5b3afe38bad8254363260928c61a083524ecc9beaf829321332fa12b417a64a452829ac2581b948a1e165cedcd92bf2922fa15d09d889294c8d24f64156128605a14120ce090a7b9a307a2a71260d04144f589c08281380128d24cc71301f9f73e557291a8d8019fecb51f1ba2a57e89224a4412ed8ab42a1c6233d88602e1d99c97463ac5ba86710001ae49d8841d913825338be8be8593113d3334c317fd040e43f3d36a369001326cce44ce7e373aaa73d331b8c3d5e10c1598e42a3932c0de711d0eb7a1df6340148634dc63c9ce72968792c22131727221b9fecddc7dfe8f98f98f9d97af2186647ad3ee6f768428ae9702c411e414ecce71e9840fb02e6ab7afd666a481583da3f82b02069d2398f6a72932c47de9234a8b423974ee5a71e7245c3f51c9c17f012117be23caaa4423acd26e8bf59cd7c20fff91cf10c1a84eca14ae585c7d5c3682ae3e7e369217bd025a87e3c9ac23f5aaba8e4bca82064515ae346f33b297832f80d90e1296018cf7bcb62b1b905d4abe29c078bd8479c428a5fb6ef61cf1ac13d64217078e079048bc3cc209205b2361e414d83abc69e19543534ff9c191134aa4712bd1517a2e167dc43cdbd067b6078d489310c72108fae9837f8cb8b5f53307cb85c3e24e80134abf5c13e1d1fdd8954a49f2a54b241dc89d9acc59a297e4d89807957345103556506d9fd46c56f0d85ae7ac7a334a88cec4a6a99321e81b034761e81453006b6c7369afc6891bfe38954605acfb7898882050177e03c227c4622e6322969b2784e32bec8394d229c8232eb9d9107097010c503a03fe3f3e3088d6261508070698a6bcc0476e8818daddaab4a3a08850544ff6f67d5d66d5733af8d138ece35f69fd453b453624df256bc62cc631ecc504f2685c4fac9e2fcd5b453f1e49d8f6e2db6374df45c447c2ac16d6580a3e819bab8e050450266701740280583ef94930509531479c60e4ed65926edeb46ecbc4eda198fe2ba2aac641a8177650eccb2014f0a38352e957928fa69aac0eb56912d43fd279b73490c38399b57ee46d30d1b0d46ab7a12309accf885d5d157f517b5c7ca43f6b3a5f16c9e06803740411bfa5cd3dc9c1e162c2711ed30904d0429080fb74a0a9d5afe6c9992db08fc638b700f059bd5c0995caeeed9d0b8bcc4228798b089bf9ce323c00fbaafe09151656822fac3bf3f01dbd86bbde26e0ca55a3ec8d933b21ad934b2a801079043406399e3891890028622fe566b6f0e46f02534ec0b0e7ee40534a64dbe81ea56c10062a4e41cf184b9bafb3e121df57843957f75b58a7c39064805d8199a278aaab42afa3a64ab2a2b6d49132d50bd279a2a9e754eae1a55a9d43b2217302924ddaa6d88656b666cfa2ddd7d615ca76a11d2080564cfe0c8f018b16f0715a4637c85ae344c4dfa9230d15f6d89146d429fca804624024496d4e0d5407c86b533cd3a3ed2c12faf97f9513ff7376f9871e66c11b3a8d1c0ef74ca4d5a568c991b3530c70821e0c0e0d74c64bf393c3aa301efd387c1edcff0812df9bc2980174922d66d7f37b39fb3a35d1182dbd474301057f88988f8df355cb8416f7758b3cfd5d47920a64d97e17b7847839a2f771b1d3bd764bfe301933031d0e09c2ee4ab349cb2e4ea4aaf38c86dd253e8db85d285a63ca23844befd7c02f345d894d74fc2bd03710548f59ad2d265ee91b0dc40a49e8d3e5e2068335ef01aa0bb9869b87e3b128bc0e1b8a6c0b0c83d9217866b1b527a4925b81837d5aedefc3906cb260e2d98b7004b5f838f6a4d7e61b20f68f51078d0a0f04aac22f0f9a49d823d67ee296b2ae6f13c1209236f58127229c1d4cbbb97b9a913ab94eb8bbd46e43e4b5ec7c36d1ab4a6581327ff992b7f4d93a0294b1dc54491ac3db7424a1f4a8624bda8d0e17bb4dc0afdbadbc9b130bad51d1588131e8229b27a029165eb06c40500acba3c68c235a062a25f5d1ad2e51ead1114a8baf418c3ac38f35a00b7e6cd47407c981b5f2c7154fc762c7d389ba3ebfe6bbe40b0b9f5dbfd71de4df372af1d9f6ce473488cbe8a5560f28bf2b58faccd7a74dcd05f2ef959e1298380ff7296dbce722b6277f092bc573cb899972117801a4207fedc0f60a3a83c958d961ebe797f7b2d75e314e63d17464c03fcc16304deLine truncated
|
||||
bs, _ = hex.DecodeString("1f8b080000096e8800ffec5d7b77dbb692ff3f9f02e1ed26ce5d93721e4dbb8eac5dd74e5b6f9bc78993ed767bba7b20129250930443807654c7f7b3efcc806f91922cdb896fdb3f128b0430180c0683df0c1e1cde3d7c75f0f6e7d7cfd9cc44e1e8cef0aeebde3950c93c95d399615b070fd8a39d874fd87ff2133566dfa874ca781c3065662265be8a4d2ac79951a9f6d87e18322aa5592ab4484f45e0dd79a705531366665233adb2d417502a100c1ea7ea54a4b108d8780e34d98ba3b7ae36f350b050fa22867266c60df321692cee4c5406d5ca185e0af6e3d1c1f397c7cfd94486c2bbe3bac03672cf421e4ff71c113b2c9eba3c49f61c3d8f7da83b9ed22be25785a148f79ce322e5c0a4a1c3fc906bbde760a650f11307490a1e8cee30368c84e1cc9ff1540bb3e76466e27eed540933631257bccfe4e99ef3dfeebb7df740450937721c0a872424622875f47c4f0453512b17f348ec39a7529c252a35b5ac673230b3bd409c82185c7ad886864b2379e86a9f8762efa1b7b3402810da4f6562a48a6bb416b2f1cccc54ba902394f109f45a08128364e36786491f29cd5231d97326fc141fbd040439ba83058c34a1189542641fd9f93976f24be8dc9750d3d6838b8be1c0e62a2bb0c4c64a196d529e0c7cad07e59317c9d883374ece07aa829e09612c875635cc3c814618f1c160614a616cac82393ba79f8c253c08802177ac8c51d12efb6a27f9f02c4f9b40a3dd098f6438df65cef7223c1546fa9cbd149970b659f9629beda720ed6da679ac5d506539b1242eeed09f2cfcd7d997658d114fa732768d4a76d943ef4b1135f27ac8ac1ba958e98483f69f77f1f242c4a1da662f54cc7df87ba062ad4021b79973006346c2507b29ce80c3924cab0a0eca86da1de0b809468654d7a423549dc55494577fea043aa43fb5a41c2ca5dc995a520e4a298c551a88d4ca2e5671ab5da19aaa969877d9ceb3664fd7de1019f7cbaac313a5258e885dd4291893a7ed0aa4366eacdc710646c19455d16b52381715ceb2d62a080d0bb3282ecb0452272187be9431e8ba70c7a1f24f0a3e40b5ed48067d2cf4a3541cb299a03a55c298fb27d3142d1ed6a252607f3ade7af4f8e9367bf46407ff7bf8e0595382290f64a677d9e35ae30bf93c4c3eb027d5fb42908fe0f5a3e2f545bb5da066b11770301c2d3d0fc504b8dda914bdd1bc873bd56bd27c1eca29ca1f1bf96cb5ac0a0117867851bed817ecae8cd06af2d8748c049823ca62673369844b636637566760671ac6e04c58e13fd9d9e924142cd815dbfc476055fa98f88f480492b3ad887fc8a5f2d5d3af920f0f4a52f9c880493281810e4a39b26feae3a7ccccd8e0efa0bd30551ac659692d19cc45060daff0a6de6e9997fd1dda95829d18c3d4c89219c84ac3b0603c0cd51943618f53c14f34cea4a182e2a9485205654250a28186390ee6e3336966758a56236086fffba07c5d972b74491af1b010ec45a950c3010d22984b077632bd33a416d20c024083bd5509287bca700ac777313f2d67627e8a29f60f1a88e26720263c0b61c284995c503e39e534edd9d96018c89208ce721c1a9de669388f805e37eb70c729401a673494d1b44841cbe3309dfa3811b9f8e43e7cf435cd7fcccecfcee347303b92fad8df83112ba7c3a106798405b1990cc004ba1f60be6ad66fa786cc08a8fd23080b92469df328911be5398a966461ad1d85746a3f69c8950da739b82810a42a09d4595c4b85749e4fd07f73daf940fed329e2193408f9439dcaf3409a7bf15827cf86e352f6a04b50fd7030867fbc5151c579594124e2acc10df13b2a79b2f80d90e109609820782312b5f500a8d7c5390de7c90c710a2b7fb9b3007bd60aee9e8880c3fd2060581c660695ce91b5e1006a5abb6aec99b5aa86e69f092b8256f548a2b7e25234f25406a8b997600f0c8f39b68641afc5a3afa62dfe8ae297148c5c5f2eef53f400dad5cec03e1d1dde8854f42c33a8646b71a7269305d66cf14b4a04ccbbe1a959535526907dd6aaf88da5d055ef709085b5915d4bad528603101661e70158046b607b6ca3cd8f16f95b996a03a6f56c9ba9389c337007ce6226272c16bed09aa7f3672ce78b9df134c62928b7de397990800451dc05fa13393d8ad1289606050857a6b8c14ce84601d8d8babdaaa5835044c8e87f37afb669bbda795d9c7028d770f6b899424e89332a5af15288400430433d1e9512eb278bf357db4e25a3b733746bb1bd594a73119b710d6eab001cc54fd1c505872a563083fb004239187caf9a2c5894a1c8737670b2ce3391af1b8bb326696f38489aaab0926904deb53930cf063c19e0d4ba54f6a1eca7b101afdbc4ae8ee84f3ee7b20470723eafdc8ca65b365a8cd6f524143c9dc80f4e475f355f341e6b0ff9cf058d17d32c04bc010adad2e786e616f4b060358990c3c0b610a4203c7c5051e8d4f2a7cb94dc45e09f384c0628d8bc0629f47275cf87c6f9391639c0842dfce51d1d027ea0be8247c18da589e80ffffe086c63aff58abb35941af92067cfc86a652364d1000e20879027bac0130920050c45fcadd1de028ce04b68d81712fcc80fd09845f22d54b70a06302b25ef50a6c2a7eefbc828eaf19a9bd9c5c52af2d51860356067691e1b6eb2bae89b90adaeac7c419a68819a3dd156f1bc730ad5a84ba5d91185805929e985dad6b16ced8c6dbfa5bb2faceb542fc25aa180fc191c199920f6eda08274acafd09586a9695f1226ce565b22c3dbd0a736a0118900912535040d109f63ed5cb38e0e29f815f4323fe8e7feea0db3ce9cab1211b71af82da55ca565e598b952030b8c10010e0c7fc945f6ab27e3531eca3e7d58bbfd393e70b59cb605f03c4dd5a6edef66f67376b4af22709bda0e06e28a59aa62f93bc1852bf4768735fb5c4d9d866adc7619be83773c6cf872d7d1b15322fbad0c8586898187677cae5f66d158a41717b4e2a0b7594fa16fe6860a8d65cc71887cf3f9043653515b5e3f2aff06c41522d54b4a8bcadc2261f9a1ca02177dbc50f176bce01540773521b87e3d128bc1e1b8a4c0b0c82d9217866b5b527ac135b81857d5aedefc0506cb270e12cc1b80a5afc04775463f0bdd07b47a08dc6d5178a95611f87cd2cec09e0bff44b415f3681aab54b0d7228da4d660eaf5cdcbdcd68955eacdc5de20729b254ff17097870b53ac8d93ff24cd6c4393409435453151241bcfad90d28792218916153a7c8f05b7825e773b390e46b7baa302492a2330454e4f20b26add1a710100abbe0cdb700da8d8e857978674b9471b0405ea2e3dc6306bce3c09e0dabcf91888afe7c6974b1c35bf1d4b1f4ca6e8baff522c106c3df8f5f638efb67985d78e4f2ef2b94e8cbe8e5560f28b8bb58fbccd343aaee82f57fcacf09441c07f39cb8bcef242c46eff057b676478352f43cf0135441efcb91dc0c6707da25b2d3d78fdeefa5aea2719cc7b3e8c9816f8Line truncated
|
||||
gr, _ = gzip.NewReader(bytes.NewBuffer(bs))
|
||||
bs, _ = ioutil.ReadAll(gr)
|
||||
Assets["index.html"] = bs
|
||||
|
||||
+58
-1
@@ -98,6 +98,7 @@ func startGUI(cfg config.GUIConfiguration, assetDir string, m *model.Model) erro
|
||||
router.Get("/rest/system", restGetSystem)
|
||||
router.Get("/rest/errors", restGetErrors)
|
||||
router.Get("/rest/discovery", restGetDiscovery)
|
||||
router.Get("/rest/report", restGetReport)
|
||||
router.Get("/qr/:text", getQR)
|
||||
|
||||
router.Post("/rest/config", restPostConfig)
|
||||
@@ -107,6 +108,8 @@ func startGUI(cfg config.GUIConfiguration, assetDir string, m *model.Model) erro
|
||||
router.Post("/rest/error", restPostError)
|
||||
router.Post("/rest/error/clear", restClearErrors)
|
||||
router.Post("/rest/discovery/hint", restPostDiscoveryHint)
|
||||
router.Post("/rest/report/enable", restPostReportEnable)
|
||||
router.Post("/rest/report/disable", restPostReportDisable)
|
||||
|
||||
mr := martini.New()
|
||||
mr.Use(csrfMiddleware)
|
||||
@@ -195,7 +198,7 @@ func restGetConfig(w http.ResponseWriter) {
|
||||
json.NewEncoder(w).Encode(encCfg)
|
||||
}
|
||||
|
||||
func restPostConfig(req *http.Request) {
|
||||
func restPostConfig(req *http.Request, m *model.Model) {
|
||||
var newCfg config.Configuration
|
||||
err := json.NewDecoder(req.Body).Decode(&newCfg)
|
||||
if err != nil {
|
||||
@@ -242,6 +245,29 @@ func restPostConfig(req *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
if newCfg.Options.UREnabled && !cfg.Options.UREnabled {
|
||||
// UR was enabled
|
||||
cfg.Options.UREnabled = true
|
||||
cfg.Options.URDeclined = false
|
||||
cfg.Options.URAccepted = usageReportVersion
|
||||
// Set the corresponding options in newCfg so we don't trigger the restart check if this was the only option change
|
||||
newCfg.Options.URDeclined = false
|
||||
newCfg.Options.URAccepted = usageReportVersion
|
||||
sendUsageRport(m)
|
||||
go usageReportingLoop(m)
|
||||
} else if !newCfg.Options.UREnabled && cfg.Options.UREnabled {
|
||||
// UR was disabled
|
||||
cfg.Options.UREnabled = false
|
||||
cfg.Options.URDeclined = true
|
||||
cfg.Options.URAccepted = 0
|
||||
// Set the corresponding options in newCfg so we don't trigger the restart check if this was the only option change
|
||||
newCfg.Options.URDeclined = true
|
||||
newCfg.Options.URAccepted = 0
|
||||
stopUsageReporting()
|
||||
} else {
|
||||
cfg.Options.URDeclined = newCfg.Options.URDeclined
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cfg.Options, newCfg.Options) {
|
||||
configInSync = false
|
||||
}
|
||||
@@ -347,6 +373,10 @@ func restGetDiscovery(w http.ResponseWriter) {
|
||||
json.NewEncoder(w).Encode(discoverer.All())
|
||||
}
|
||||
|
||||
func restGetReport(w http.ResponseWriter, m *model.Model) {
|
||||
json.NewEncoder(w).Encode(reportData(m))
|
||||
}
|
||||
|
||||
func getQR(w http.ResponseWriter, params martini.Params) {
|
||||
code, err := qr.Encode(params["text"], qr.M)
|
||||
if err != nil {
|
||||
@@ -358,6 +388,33 @@ func getQR(w http.ResponseWriter, params martini.Params) {
|
||||
w.Write(code.PNG())
|
||||
}
|
||||
|
||||
func restPostReportEnable(m *model.Model) {
|
||||
if cfg.Options.UREnabled {
|
||||
return
|
||||
}
|
||||
|
||||
cfg.Options.UREnabled = true
|
||||
cfg.Options.URDeclined = false
|
||||
cfg.Options.URAccepted = usageReportVersion
|
||||
|
||||
go usageReportingLoop(m)
|
||||
sendUsageRport(m)
|
||||
saveConfig()
|
||||
}
|
||||
|
||||
func restPostReportDisable(m *model.Model) {
|
||||
if !cfg.Options.UREnabled {
|
||||
return
|
||||
}
|
||||
|
||||
cfg.Options.UREnabled = false
|
||||
cfg.Options.URDeclined = true
|
||||
cfg.Options.URAccepted = 0
|
||||
|
||||
stopUsageReporting()
|
||||
saveConfig()
|
||||
}
|
||||
|
||||
func basic(username string, passhash string) http.HandlerFunc {
|
||||
return func(res http.ResponseWriter, req *http.Request) {
|
||||
if validAPIKey(req.Header.Get("X-API-Key")) {
|
||||
|
||||
@@ -393,6 +393,18 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Options.UREnabled && cfg.Options.URAccepted < usageReportVersion {
|
||||
l.Infoln("Anonymous usage report has changed; revoking acceptance")
|
||||
cfg.Options.UREnabled = false
|
||||
}
|
||||
if cfg.Options.UREnabled {
|
||||
go usageReportingLoop(m)
|
||||
go func() {
|
||||
time.Sleep(10 * time.Minute)
|
||||
sendUsageRport(m)
|
||||
}()
|
||||
}
|
||||
|
||||
<-stop
|
||||
l.Okln("Exiting")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/calmh/syncthing/model"
|
||||
)
|
||||
|
||||
// Current version number of the usage report, for acceptance purposes. If
|
||||
// fields are added or changed this integer must be incremented so that users
|
||||
// are prompted for acceptance of the new report.
|
||||
const usageReportVersion = 1
|
||||
|
||||
var stopUsageReportingCh = make(chan struct{})
|
||||
|
||||
func reportData(m *model.Model) map[string]interface{} {
|
||||
res := make(map[string]interface{})
|
||||
res["uniqueID"] = strings.ToLower(certID([]byte(myID)))[:6]
|
||||
res["version"] = Version
|
||||
res["platform"] = runtime.GOOS + "-" + runtime.GOARCH
|
||||
res["numRepos"] = len(cfg.Repositories)
|
||||
res["numNodes"] = len(cfg.Nodes)
|
||||
|
||||
var totFiles, maxFiles int
|
||||
var totBytes, maxBytes int64
|
||||
for _, repo := range cfg.Repositories {
|
||||
files, _, bytes := m.GlobalSize(repo.ID)
|
||||
totFiles += files
|
||||
totBytes += bytes
|
||||
if files > maxFiles {
|
||||
maxFiles = files
|
||||
}
|
||||
if bytes > maxBytes {
|
||||
maxBytes = bytes
|
||||
}
|
||||
}
|
||||
|
||||
res["totFiles"] = totFiles
|
||||
res["repoMaxFiles"] = maxFiles
|
||||
res["totMiB"] = totBytes / 1024 / 1024
|
||||
res["repoMaxMiB"] = maxBytes / 1024 / 1024
|
||||
|
||||
var mem runtime.MemStats
|
||||
runtime.ReadMemStats(&mem)
|
||||
res["memoryUsageMiB"] = mem.Sys / 1024 / 1024
|
||||
|
||||
var perf float64
|
||||
for i := 0; i < 5; i++ {
|
||||
p := cpuBench()
|
||||
if p > perf {
|
||||
perf = p
|
||||
}
|
||||
}
|
||||
res["sha256Perf"] = perf
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func sendUsageRport(m *model.Model) error {
|
||||
d := reportData(m)
|
||||
var b bytes.Buffer
|
||||
json.NewEncoder(&b).Encode(d)
|
||||
_, err := http.Post("https://data.syncthing.net/newdata", "application/json", &b)
|
||||
return err
|
||||
}
|
||||
|
||||
func usageReportingLoop(m *model.Model) {
|
||||
l.Infoln("Starting usage reporting")
|
||||
t := time.NewTicker(86400 * time.Second)
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case <-stopUsageReportingCh:
|
||||
break loop
|
||||
case <-t.C:
|
||||
sendUsageRport(m)
|
||||
}
|
||||
}
|
||||
l.Infoln("Stopping usage reporting")
|
||||
}
|
||||
|
||||
func stopUsageReporting() {
|
||||
stopUsageReportingCh <- struct{}{}
|
||||
}
|
||||
|
||||
// Returns CPU performance as a measure of single threaded SHA-256 MiB/s
|
||||
func cpuBench() float64 {
|
||||
chunkSize := 100 * 1 << 10
|
||||
h := sha256.New()
|
||||
bs := make([]byte, chunkSize)
|
||||
rand.Reader.Read(bs)
|
||||
|
||||
t0 := time.Now()
|
||||
b := 0
|
||||
for time.Since(t0) < 125*time.Millisecond {
|
||||
h.Write(bs)
|
||||
b += chunkSize
|
||||
}
|
||||
h.Sum(nil)
|
||||
d := time.Since(t0)
|
||||
return float64(int(float64(b)/d.Seconds()/(1<<20)*100)) / 100
|
||||
}
|
||||
@@ -157,6 +157,10 @@ type OptionsConfiguration struct {
|
||||
StartBrowser bool `xml:"startBrowser" default:"true"`
|
||||
UPnPEnabled bool `xml:"upnpEnabled" default:"true"`
|
||||
|
||||
UREnabled bool `xml:"urEnabled"` // If true, send usage reporting data
|
||||
URDeclined bool `xml:"urDeclined"` // If true, don't ask again
|
||||
URAccepted int `xml:"urAccepted"` // Accepted usage reporting version
|
||||
|
||||
Deprecated_ReadOnly bool `xml:"readOnly,omitempty" json:"-"`
|
||||
Deprecated_GUIEnabled bool `xml:"guiEnabled,omitempty" json:"-"`
|
||||
Deprecated_GUIAddress string `xml:"guiAddress,omitempty" json:"-"`
|
||||
|
||||
+48
-9
@@ -30,21 +30,24 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
||||
$scope.seenError = '';
|
||||
$scope.model = {};
|
||||
$scope.repos = {};
|
||||
$scope.reportData = {};
|
||||
$scope.reportPreview = false;
|
||||
|
||||
// Strings before bools look better
|
||||
$scope.settings = [
|
||||
{id: 'ListenStr', descr: 'Sync Protocol Listen Addresses', type: 'text', restart: true},
|
||||
{id: 'MaxSendKbps', descr: 'Outgoing Rate Limit (KiB/s)', type: 'number', restart: true},
|
||||
{id: 'RescanIntervalS', descr: 'Rescan Interval (s)', type: 'number', restart: true},
|
||||
{id: 'ReconnectIntervalS', descr: 'Reconnect Interval (s)', type: 'number', restart: true},
|
||||
{id: 'ParallelRequests', descr: 'Max Outstanding Requests', type: 'number', restart: true},
|
||||
{id: 'MaxChangeKbps', descr: 'Max File Change Rate (KiB/s)', type: 'number', restart: true},
|
||||
{id: 'ListenStr', descr: 'Sync Protocol Listen Addresses', type: 'text'},
|
||||
{id: 'MaxSendKbps', descr: 'Outgoing Rate Limit (KiB/s)', type: 'number'},
|
||||
{id: 'RescanIntervalS', descr: 'Rescan Interval (s)', type: 'number'},
|
||||
{id: 'ReconnectIntervalS', descr: 'Reconnect Interval (s)', type: 'number'},
|
||||
{id: 'ParallelRequests', descr: 'Max Outstanding Requests', type: 'number'},
|
||||
{id: 'MaxChangeKbps', descr: 'Max File Change Rate (KiB/s)', type: 'number'},
|
||||
|
||||
{id: 'GlobalAnnEnabled', descr: 'Global Discovery', type: 'bool', restart: true},
|
||||
{id: 'LocalAnnEnabled', descr: 'Local Discovery', type: 'bool', restart: true},
|
||||
{id: 'LocalAnnPort', descr: 'Local Discovery Port', type: 'number', restart: true},
|
||||
{id: 'LocalAnnPort', descr: 'Local Discovery Port', type: 'number'},
|
||||
{id: 'LocalAnnEnabled', descr: 'Local Discovery', type: 'bool'},
|
||||
{id: 'GlobalAnnEnabled', descr: 'Global Discovery', type: 'bool'},
|
||||
{id: 'StartBrowser', descr: 'Start Browser', type: 'bool'},
|
||||
{id: 'UPnPEnabled', descr: 'Enable UPnP', type: 'bool'},
|
||||
{id: 'UREnabled', descr: 'Anonymous Usage Reporting', type: 'bool'},
|
||||
];
|
||||
|
||||
$scope.guiSettings = [
|
||||
@@ -544,11 +547,47 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
||||
$scope.repos = repoMap($scope.config.Repositories);
|
||||
|
||||
$scope.refresh();
|
||||
|
||||
if (!$scope.config.Options.UREnabled && !$scope.config.Options.URDeclined) {
|
||||
// If usage reporting has been neither accepted nor declined,
|
||||
// we want to ask the user to make a choice. But we don't want
|
||||
// to bug them during initial setup, so we set a cookie with
|
||||
// the time of the first visit. When that cookie is present
|
||||
// and the time is more than four hours ago, we ask the
|
||||
// question.
|
||||
|
||||
var firstVisit = document.cookie.replace(/(?:(?:^|.*;\s*)firstVisit\s*\=\s*([^;]*).*$)|^.*$/, "$1");
|
||||
if (!firstVisit) {
|
||||
document.cookie = "firstVisit=" + Date.now() + ";max-age=" + 30*24*3600;
|
||||
} else {
|
||||
if (+firstVisit < Date.now() - 4*3600*1000){
|
||||
$('#ur').modal({backdrop: 'static', keyboard: false});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$http.get(urlbase + '/config/sync').success(function (data) {
|
||||
$scope.configInSync = data.configInSync;
|
||||
});
|
||||
|
||||
$http.get(urlbase + '/report').success(function (data) {
|
||||
$scope.reportData = data;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.acceptUR = function () {
|
||||
$scope.config.Options.UREnabled = true;
|
||||
$scope.config.Options.URDeclined = false;
|
||||
$scope.saveConfig();
|
||||
$('#ur').modal('hide');
|
||||
};
|
||||
|
||||
$scope.declineUR = function () {
|
||||
$scope.config.Options.UREnabled = false;
|
||||
$scope.config.Options.URDeclined = true;
|
||||
$scope.saveConfig();
|
||||
$('#ur').modal('hide');
|
||||
};
|
||||
|
||||
$scope.init();
|
||||
|
||||
+27
-1
@@ -564,7 +564,7 @@ found in the LICENSE file.
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title"> Settings</h4>
|
||||
<h4 class="modal-title">Settings</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form role="form">
|
||||
@@ -611,6 +611,32 @@ found in the LICENSE file.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Usage report modal -->
|
||||
|
||||
<div id="ur" class="modal fade">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header alert alert-success">
|
||||
<h4 class="modal-title">Allow Anonymous Usage Reporting?</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
The encrypted usage report is sent daily. It is used to track common platforms, repo sizes and app versions. If the reported data set is changed you will be prompted with this dialog again.
|
||||
</p>
|
||||
<p>
|
||||
The aggregated statistics are publicly available at <a href="https://data.syncthing.net/">https://data.syncthing.net/</a>.
|
||||
</p>
|
||||
<button type="button" class="btn btn-default" ng-show="!reportPreview" ng-click="reportPreview = true">Preview Usage Report</button>
|
||||
<pre ng-if="reportPreview"><small>{{reportData | json}}</small></pre>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-success" ng-click="acceptUR()"><span class="glyphicon glyphicon-ok"></span> Yes</button>
|
||||
<button type="button" class="btn btn-danger" ng-click="declineUR()"><span class="glyphicon glyphicon-remove"></span> No</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="angular.min.js"></script>
|
||||
<script src="jquery-2.0.3.min.js"></script>
|
||||
|
||||
Reference in new issue
Block a user