Anonymous Usage Reporting

This commit is contained in:
Jakob Borg committed 2014-06-11 20:06:53 +02:00
1 parent 7454670b0a
commit f40f3b3b7b
7 files changed
+260 -13

No files matched your search

+2 -2
View File
@@ -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
View File
@@ -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")) {
+12
View File
@@ -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")
}
+109
View File
@@ -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
}
+4
View File
@@ -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
View File
@@ -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
View File
@@ -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>&emsp;Yes</button>
<button type="button" class="btn btn-danger" ng-click="declineUR()"><span class="glyphicon glyphicon-remove"></span>&emsp;No</button>
</div>
</div>
</div>
</div>
<script src="angular.min.js"></script>
<script src="jquery-2.0.3.min.js"></script>