1
0
forked from iarv/nntpchan

Compare commits

...

1196 Commits

Author SHA1 Message Date
Jeff Becker 22dc099105 fix 2017-09-11 16:50:57 -04:00
Jeff Becker 723fa5aff5 fix 2017-09-11 16:48:41 -04:00
Jeff Becker 57b6b5050e fix 2017-09-11 16:43:28 -04:00
Jeff Becker 52634b7edd optimizations 2017-09-11 16:37:04 -04:00
Jeff Becker 412c2ad4ca templates 2017-09-09 11:04:48 -04:00
Jeff Becker 7165f6eb4a fixes 2017-09-09 11:04:37 -04:00
Jeff Becker eed8c07ef6 add postgres vendored 2017-09-09 10:20:33 -04:00
Jeff Becker ea91db2f58 fix stuff up 2017-09-09 09:45:45 -04:00
Jeff Becker 0cd12cf944 update docs 2017-09-04 07:58:40 -04:00
Jeff Becker eed0fc8001 fix docs 2017-09-04 07:55:57 -04:00
Jeff Becker efda3efd56 update readme 2017-08-29 08:26:51 -04:00
Jeff Becker 81a08bb407 gut libsodium for rewrite 2017-08-27 11:24:37 -04:00
Jeff Becker bb890e716b bump daemon version 2017-08-26 12:44:08 -04:00
Jeff Becker 1a2c5b9e4a remove use of libsodium in docs 2017-08-26 12:40:27 -04:00
Jeff Becker 358fe300ed use pure go target by default 2017-08-26 12:35:10 -04:00
Jeff Becker f4a6988f11 works OMG YESH 2017-08-26 12:33:13 -04:00
Jeff Becker f2d854d88f omg public key derivation works, signing still suck 2017-08-26 11:47:40 -04:00
Jeff Becker 4ede62a667 fix? 2017-08-26 10:48:47 -04:00
Jeff Becker 59ea3da355 add tests and try making no libsodium version work properly 2017-08-26 10:41:28 -04:00
Jeff Becker 2983eb6fbd start preparing for gutting of libsodium dependancy 2017-08-26 09:40:24 -04:00
Jeff Becker 0870b270cc fix date format in us locale 2017-08-25 12:47:35 -04:00
Jeff Becker f3e76a1e0f use big ass query for calculating post history 2017-08-25 12:42:25 -04:00
Jeff Becker 7d56d68d14 add logging 2017-08-25 11:11:49 -04:00
Jeff Becker 7524db96fe move history.html cache invalidation to expire with frontpage 2017-08-25 11:07:22 -04:00
Jeff Becker bd67be0280 add logging 2017-08-25 11:03:58 -04:00
Jeff Becker 5be6c9f7e8 document expire tool 2017-08-25 10:58:56 -04:00
Jeff Becker e78286cc06 change genSignKeypair to genNaclSignKeypair or stuff 2017-08-25 10:56:17 -04:00
Jeff Becker fea75f7200 try fixing signing omg this suxass 2017-08-25 10:52:57 -04:00
Jeff Becker d61228215e tabify 2017-08-25 10:43:29 -04:00
Jeff Becker cc5d94ee5f try reverting to old key derivation function 2017-08-25 10:37:46 -04:00
Jeff Becker 2152cd3246 idk 2017-08-25 10:33:27 -04:00
Jeff Becker c6a79b8893 more stuff see if it works idklol 2017-08-25 10:28:47 -04:00
Jeff Becker 838f2b8ca7 fix order 2017-08-25 10:14:16 -04:00
Jeff Becker 88d723219a add debugging for testing 2017-08-25 10:11:23 -04:00
Jeff Becker dbb5897305 fix nil, initialize public and private key buffers 2017-08-25 09:55:26 -04:00
Jeff Becker 892a7ea58b unbreak make it compile 2017-08-25 09:47:32 -04:00
Jeff Becker 64c52e327a unbreak maybe? 2017-08-25 09:37:05 -04:00
Jeff Becker 86b3d3ce62 probably broken 2017-08-25 09:30:34 -04:00
Jeff Becker aa3cf130b3 don't use libsodium for new sigs 2017-08-25 08:52:41 -04:00
Jeff Becker ed2f88c0fc add ed25519-blake2b signature support 2017-08-25 08:20:06 -04:00
Jeff Becker 2d090269c5 whitespace 2017-08-23 08:24:34 -04:00
Jeff Becker aa637b7cb6 update css 2017-08-23 08:05:19 -04:00
Jeff Becker 38b24825fd update css 2017-08-23 08:03:57 -04:00
Jeff Becker bb1b9f427d update css 2017-08-23 08:01:42 -04:00
Jeff Becker c18152a7ba css fixes 2017-08-23 08:00:12 -04:00
Jeff Becker 17e89387b5 fix typo 2017-08-23 07:58:10 -04:00
Jeff Becker 89c5773625 add new mod's css rules 2017-08-23 07:56:13 -04:00
Jeff Becker 1dc800b89c add xmr address 2017-08-23 07:42:04 -04:00
Jeff Becker c1f9191045 update readme
Signed-off-by: Jeff Becker <jeff@i2p.rocks>
2017-08-23 06:18:53 -04:00
Jeff Becker bbefe94e8a update gitgud url 2017-08-23 06:15:25 -04:00
Jeff Becker d28f272b94 Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2017-08-13 20:17:12 -04:00
Jeff Becker 4770129ad6 update asset 2017-08-13 20:16:58 -04:00
Jeff e87005a178 make captcha readable 2017-08-12 18:22:44 -04:00
Jeff 1e69493eef Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2017-08-12 18:20:13 -04:00
Jeff 1a70ff9d92 add captcha to placebo template 2017-08-12 18:19:49 -04:00
Jeff Becker 41a8541660 add expire tool 2017-08-08 18:48:07 -04:00
Jeff Becker f61470468b add expire tool 2017-08-08 18:45:51 -04:00
Jeff Becker 23ae28bc71 fix bump bug 2017-08-08 18:38:48 -04:00
Jeff Becker fa5e250595 fix history.html 2017-08-08 18:30:59 -04:00
Jeff Becker f079a1fee4 fix history.html 2017-08-08 18:26:59 -04:00
Jeff Becker 5e66346662 eh whatever this should work 2017-08-08 09:32:42 -04:00
Jeff Becker d48b585fcf eh whatever this should work 2017-08-08 09:32:18 -04:00
Jeff Becker 32e9e4b3eb add log 2017-08-08 09:24:44 -04:00
Jeff Becker a60ecff7e3 add log 2017-08-08 09:22:21 -04:00
Jeff Becker 54b8b60edd add initial local spam filter 2017-08-08 09:18:31 -04:00
Jeff 2e4c42ff8a update placebo template 2017-08-07 16:09:00 -04:00
Jeff e9cb9e4f46 fix 2017-08-07 16:06:51 -04:00
Jeff 1753e2e54b fix 2017-08-07 16:05:40 -04:00
Jeff c2c2146ad3 try fixing frontend function of model 2017-08-07 16:03:36 -04:00
Jeff 1f1dc6a63b Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2017-08-05 10:13:32 -04:00
Jeff f07a6faec6 initial base neochan app 2017-08-05 10:13:15 -04:00
Jeff Becker 51e0763faf Revert "more c++ stuff probably broken"
This reverts commit 5ea8b1b245.
2017-08-04 10:43:49 -04:00
Jeff Becker 5ea8b1b245 more c++ stuff probably broken 2017-08-04 10:39:29 -04:00
Jeff aecbe2a5a9 do not use banned newsgroups 2017-08-03 21:57:59 -04:00
Jeff cff13becaf 404 for banned newsgroups 2017-08-03 21:38:18 -04:00
Jeff a06a671415 fix ip bans lol 2017-08-03 16:23:34 -04:00
Jeff 70feeed809 fix previous commit, make it compile 2017-08-03 12:10:19 -04:00
Jeff 6af4470473 fix last 2017-08-03 12:09:11 -04:00
Jeff bdabd25867 fix error message spam 2017-08-03 12:07:12 -04:00
Jeff d301021122 admin css 2017-07-30 18:37:39 -04:00
Jeff 741ded6694 fix pubkey tripcode 2017-07-30 18:20:14 -04:00
Jeff 2074e49d75 tripcodes 2017-07-30 18:17:10 -04:00
Jeff 809863c472 tripcodes 2017-07-30 18:16:02 -04:00
Jeff Becker be54d399f3 css fix 2017-07-29 16:36:27 -04:00
Jeff Becker 76a3288d8c more 2017-07-27 10:10:40 -04:00
Jeff Becker 3d4d106554 change alpha 2017-07-27 09:51:23 -04:00
Jeff Becker c7da354244 fix board page 2017-07-27 09:46:58 -04:00
Jeff Becker acebb66227 fix placement 2017-07-27 09:46:01 -04:00
Jeff Becker 3a273ccf08 add navbar to bottom 2017-07-27 09:44:58 -04:00
Jeff Becker dbc47f8c65 fix pagination on ukko 2017-07-27 09:44:01 -04:00
Jeff Becker c03c8c370e Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2017-07-27 09:42:15 -04:00
Jeff Becker a6e5fd13e0 add viewport 2017-07-27 09:42:04 -04:00
Jeff 37ebcc2693 fix bug in feeds 2017-07-20 21:35:48 -04:00
Jeff 31a1109372 add fagarrows 2017-07-10 08:20:22 -04:00
Jeff d241137ded cssfix 2017-07-03 18:33:27 -04:00
Jeff b78f044b0b mor 2017-07-03 18:18:38 -04:00
Jeff 4262f4dc59 mor 2017-07-03 18:16:02 -04:00
Jeff 3629eb41d9 mor 2017-07-03 18:14:47 -04:00
Jeff d21efc7fd2 racism 2017-07-03 18:04:02 -04:00
Jeff Becker 90652f8e7b make sage greyscale not red 2017-06-28 18:15:21 -04:00
Jeff Becker 4469462cb7 fixes 2017-05-03 18:31:19 -04:00
Jeff Becker 37598e187d more 2017-05-03 13:44:35 -04:00
Jeff Becker e4a9db3f11 storage works 2017-05-03 13:33:04 -04:00
Jeff Becker 0965d34fbb more 2017-05-03 11:38:48 -04:00
Jeff Becker 89c2398a96 more 2017-05-03 11:37:09 -04:00
Jeff Becker 279faa56b7 more fixes 2017-05-03 11:01:32 -04:00
Jeff Becker 19d75eb917 make it work 2017-05-03 09:44:42 -04:00
Jeff Becker dba185c6aa compiles 2017-05-03 09:15:06 -04:00
Jeff Becker 07e62d2057 more 2017-05-03 08:17:53 -04:00
Jeff Becker 2f122529b0 more 2017-05-03 08:09:23 -04:00
Jeff Becker 942294317a make backend die when streaming is done 2017-04-23 08:30:28 -04:00
Jeff Becker cfaa96b82c add feed policy for inbound feeds in default section of feeds.ini 2017-04-23 08:24:12 -04:00
Jeff Becker cc467ac312 make it compile 2017-04-23 08:07:17 -04:00
Jeff Becker 0966a247e5 fix ? 2017-04-23 08:05:21 -04:00
Jeff Becker 4f3ac9f256 typo in error message 2017-04-23 08:00:29 -04:00
Jeff Becker e9620558ac immediate return 2017-04-23 08:00:01 -04:00
Jeff Becker cac9979280 revert 2017-04-23 07:58:45 -04:00
Jeff Becker fdb6831064 nil check 2017-04-23 07:58:17 -04:00
Jeff Becker fbafc56b4c make inbound nntp check feed policy 2017-04-23 07:57:50 -04:00
Jeff Becker 9e291b1c5a fix feed policy logic 2017-04-23 07:53:56 -04:00
Jeff Becker 8d4778c2d7 add board list to front page 2017-04-22 10:14:51 -04:00
Jeff Becker 0abb5882ec more fixes 2017-04-22 09:42:04 -04:00
Jeff Becker 96f51c9862 fix typo 2017-04-22 09:39:06 -04:00
Jeff Becker 872c5d3757 Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2017-04-22 09:36:30 -04:00
Jeff Becker 66c1adfece update board list template 2017-04-22 09:36:16 -04:00
Jeff 66655b18d5 Merge pull request #147 from majestrate/HEAD
make nntp connection send keepalive periodically
2017-04-22 07:07:47 -04:00
Jeff Becker 0e2c1badcd make nntp connection send keepalive periodically 2017-04-22 07:05:56 -04:00
Jeff f370a4ccbd fug 2017-04-20 18:08:32 -04:00
Jeff cff94dc8d8 fug 2017-04-20 18:07:07 -04:00
Jeff db03367945 fix 2017-04-20 18:00:59 -04:00
Jeff aca6a0dfa4 fix 2017-04-20 17:47:33 -04:00
Jeff Becker 238ce08337 eh 2017-04-19 16:57:27 -04:00
Jeff Becker ba113fa90f add frontend data thingy 2017-04-19 16:55:24 -04:00
Jeff Becker f9e314d949 undo 2017-04-19 16:51:19 -04:00
Jeff Becker 359317457b invert color 2017-04-19 16:44:58 -04:00
Jeff Becker 648878235e css 2017-04-19 16:43:30 -04:00
Jeff Becker d4ab0ff5d0 css 2017-04-19 16:19:39 -04:00
Jeff Becker fff6b502fd css 2017-04-19 16:17:08 -04:00
Jeff Becker 0cea9f1255 more og stuff 2017-04-19 12:27:05 -04:00
Jeff Becker bcc2c3fae7 inject prefix into thread template 2017-04-19 12:25:59 -04:00
Jeff Becker 04a3bb2c39 more og stuff 2017-04-19 12:24:35 -04:00
Jeff Becker 6beed4053a more og stuff 2017-04-19 12:22:29 -04:00
Jeff Becker 0ef8b3eb2b more og stuff 2017-04-19 12:21:23 -04:00
Jeff Becker 70a63ca296 put prefix in frontpage 2017-04-19 12:10:45 -04:00
Jeff Becker 18c9512f5d add more og 2017-04-19 12:08:48 -04:00
Jeff Becker 386ccfdcf0 more og stuff 2017-04-19 12:05:27 -04:00
Jeff Becker 72d4fdfdbb fix url 2017-04-19 11:59:01 -04:00
Jeff Becker 607ef72af0 fix caching 2017-04-19 11:55:51 -04:00
Jeff Becker 6554645428 more og stuff 2017-04-19 11:50:11 -04:00
Jeff Becker 23bfe82ca3 fix url 2017-04-19 11:46:16 -04:00
Jeff Becker b1be5f67d3 more 2017-04-19 11:45:14 -04:00
Jeff Becker 308978914f add og meta tags 2017-04-19 11:43:09 -04:00
Jeff Becker 6a37c6ec87 change css link 2017-04-19 11:33:05 -04:00
Jeff Becker 9ab0f519a3 fix 404 2017-04-19 11:30:45 -04:00
Jeff Becker d10fe80739 fix up faq style 2017-04-19 11:19:55 -04:00
Jeff Becker 248dcba2e6 hide topic too 2017-04-19 11:15:34 -04:00
Jeff Becker e6e2ed4705 css 2017-04-19 11:13:48 -04:00
Jeff Becker abdd39bbdf css 2017-04-19 11:11:49 -04:00
Jeff Becker 22fe5cf4e5 add id for thread 2017-04-19 11:09:26 -04:00
Jeff Becker baa8d8d5ac fix js 2017-04-19 11:07:15 -04:00
Jeff Becker 120357dacd thread / post hider 2017-04-19 11:05:32 -04:00
Jeff Becker 0e68b9bc1f fix frontpage 2017-04-19 10:26:43 -04:00
Jeff Becker 9703acb04b fix frontpage 2017-04-19 10:24:02 -04:00
Jeff Becker e4b0990375 morwe 2017-04-19 10:19:59 -04:00
Jeff Becker d548c1014e css 2017-04-19 10:14:22 -04:00
Jeff Becker c4ccbad74b css 2017-04-19 10:13:30 -04:00
Jeff Becker 490f8f973a css 2017-04-19 10:12:53 -04:00
Jeff Becker a143636d6c css 2017-04-19 10:02:58 -04:00
Jeff Becker 1da1811d13 css 2017-04-19 10:01:27 -04:00
Jeff Becker d084bf6d48 css 2017-04-19 09:55:56 -04:00
Jeff Becker e3e086739c css 2017-04-19 09:54:02 -04:00
Jeff Becker 4a870a8335 css 2017-04-19 09:53:03 -04:00
Jeff Becker caf7b14e80 add user css override stubs 2017-04-19 09:49:13 -04:00
Jeff Becker ead00a7148 more css 2017-04-19 09:42:55 -04:00
Jeff Becker b0524645c2 fix sage in model 2017-04-19 09:39:30 -04:00
Jeff Becker 304cd79d20 add subject 2017-04-19 09:33:06 -04:00
Jeff Becker 3b101236f7 css 2017-04-19 09:26:23 -04:00
Jeff Becker b0fd79e415 css 2017-04-19 09:24:17 -04:00
Jeff Becker 24db116e4e css 2017-04-19 09:21:16 -04:00
Jeff Becker 787da56d16 Revert "more css"
This reverts commit 84e568b753.
2017-04-19 09:08:41 -04:00
Jeff Becker 84e568b753 more css 2017-04-19 09:05:31 -04:00
Jeff Becker 8c9720f6c5 more css 2017-04-19 09:04:22 -04:00
Jeff Becker 40d588f5a4 more css 2017-04-19 08:58:41 -04:00
Jeff Becker f18ece1f00 add logo 2017-04-19 08:55:52 -04:00
Jeff Becker bf35e678da css tweaks 2017-04-19 08:22:00 -04:00
Jeff Becker 893f1ff9db css tweaks 2017-04-19 08:20:55 -04:00
Jeff Becker de0f12ebc8 fix 2017-04-19 08:17:05 -04:00
Jeff Becker 484114872c fix 2017-04-19 08:15:57 -04:00
Jeff Becker 157a318175 fix 2017-04-19 08:13:54 -04:00
Jeff Becker 7af1587f33 add overchan.js to overboard 2017-04-19 07:32:32 -04:00
Jeff Becker b83b75338c add quick reply (initial) 2017-04-19 07:27:40 -04:00
Jeff Becker eeb57e3ae6 add posts excluded count 2017-04-19 07:03:36 -04:00
Jeff Becker 4da6a3cdbb more 2017-04-18 20:15:19 -04:00
Jeff Becker 0a7aae55e6 more 2017-04-18 20:13:51 -04:00
Jeff Becker 8c5f6e9cde more 2017-04-18 20:12:14 -04:00
Jeff Becker d37274ac36 more 2017-04-18 20:11:47 -04:00
Jeff Becker 87e790570e more 2017-04-18 20:10:36 -04:00
Jeff Becker 5aad791819 more 2017-04-18 20:08:44 -04:00
Jeff Becker 00c34b458b more 2017-04-18 20:07:46 -04:00
Jeff Becker 69c947774d more 2017-04-18 20:06:00 -04:00
Jeff Becker ff4336595b more 2017-04-18 20:04:37 -04:00
Jeff Becker 71121a8421 more 2017-04-18 20:02:48 -04:00
Jeff Becker 546cf9677d more 2017-04-18 20:00:38 -04:00
Jeff Becker e5346917be more 2017-04-18 19:58:24 -04:00
Jeff Becker ad3b721134 more 2017-04-18 19:57:18 -04:00
Jeff Becker f2e723de4f more 2017-04-18 19:56:12 -04:00
Jeff Becker 739f2c2291 more 2017-04-18 19:55:37 -04:00
Jeff Becker 066c514bf0 more 2017-04-18 19:54:08 -04:00
Jeff Becker 0f05488466 more 2017-04-18 19:52:10 -04:00
Jeff Becker f35d7b29e0 more 2017-04-18 19:50:00 -04:00
Jeff Becker efcd18bc8a more 2017-04-18 19:47:08 -04:00
Jeff Becker 881ca6cdf0 more 2017-04-18 19:45:36 -04:00
Jeff Becker 7c6bb5c40d placebo 2017-04-18 19:42:46 -04:00
Jeff Becker e9e46e1f59 add refactored rewrite 2017-04-16 14:11:11 -04:00
Jeff Becker c965f0f7af more 2017-04-14 06:24:53 -04:00
Jeff Becker e02f0fc3fd Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2017-04-05 09:15:47 -04:00
Jeff Becker 48cc9a6b6b fix css bug 2017-04-05 09:15:34 -04:00
Jeff fc64ea0acf clear existing file 2017-04-04 12:54:17 -04:00
Jeff 7e728a4a0a typo 2017-04-04 12:53:10 -04:00
Jeff Becker 77d87c0856 proper cleanup 2017-04-04 11:08:45 -04:00
Jeff Becker c871e6ccd3 cleanup 2017-04-04 11:07:50 -04:00
Jeff Becker 28a30bdd3d don't do a short write 2017-04-04 11:04:14 -04:00
Jeff Becker a66d31f447 enforce limits better 2017-04-04 11:01:02 -04:00
Jeff Becker f482c8972e tweaks 2017-04-04 10:40:43 -04:00
Jeff Becker 8b5952f66b add configurable max message sizes 2017-04-04 10:31:41 -04:00
Jeff Becker fa66537f9e update docs 2017-04-04 09:01:43 -04:00
Jeff Becker 08aaac492e switch to make for build 2017-04-04 09:01:32 -04:00
Jeff Becker 665849e016 remove gx stuff 2017-04-04 08:27:03 -04:00
Jeff Becker e87d739392 refactor mod stuff 2017-04-04 07:48:45 -04:00
Jeff Becker e8fa40c0ca fix boards.html 2017-04-03 21:35:09 -04:00
Jeff Becker 279ca91043 typo 2017-04-03 16:54:56 -04:00
Jeff Becker af7205e8fe fix 2017-04-03 16:53:00 -04:00
Jeff Becker ce7170c438 faster 2017-04-03 16:49:40 -04:00
Jeff Becker 9c60901332 update readme 2017-04-03 10:10:46 -04:00
Jeff Becker f0b3de1c6e update build.sh to use in repo source for daemon 2017-04-03 10:05:28 -04:00
Jeff Becker 3a6cbf9de6 move srndv2 to nntpchan repo with vendored deps so that nothing breaks every again
this deprecates the github.com/majestrate/srndv2 repo
2017-04-03 10:00:38 -04:00
Jeff Becker eb0ef957a4 more readme changes 2017-04-03 09:46:22 -04:00
Jeff Becker 665c52fbf6 fix headers in readme 2017-04-03 09:44:26 -04:00
Jeff Becker 5f8aa9f993 clarify what the network graph is 2017-04-02 18:28:42 -04:00
Jeff Becker 5a13dc4816 fix typo 2017-04-02 18:20:20 -04:00
Jeff Becker ddb07b482b more 2017-04-02 18:17:36 -04:00
Jeff Becker 9841bd74e3 css fix 2017-04-02 14:26:06 -04:00
Jeff Becker f35def74c3 css fixes 2017-04-02 14:15:19 -04:00
Jeff Becker 297848c8c3 ammend css from anon
thnx
2017-04-02 10:31:13 -04:00
Jeff Becker e0c35620b0 css fix for censor ui 2017-03-30 09:42:34 -04:00
Jeff Becker 5575bd2ddc close tag 2017-03-30 09:38:28 -04:00
Jeff Becker 35bc32d3b1 span -> div 2017-03-30 09:36:46 -04:00
Jeff Becker 1dbcd224ad typofix 2017-03-30 09:32:06 -04:00
Jeff Becker 6247d0cfff * try fixing report form
* make captcha widget optional
2017-03-30 08:51:59 -04:00
Jeff Becker bff7dadaa1 dont cache 2017-03-20 19:59:32 -04:00
Jeff Becker ccaa23c9d8 dont cache 2017-03-20 19:57:18 -04:00
Jeff 6ebb563fbb fix css 2017-02-06 04:40:24 -05:00
Jeff Becker d70639dcb6 fix 2017-02-05 13:14:12 -05:00
Jeff Becker 05ef278693 "disable" catalog link 2017-02-05 12:12:44 -05:00
Jeff Becker 20f442f8f2 more 2017-02-05 11:41:35 -05:00
Jeff Becker 026c5039a9 more 2017-02-05 11:40:27 -05:00
Jeff Becker f83b4340c6 more 2017-02-05 11:35:47 -05:00
Jeff Becker 674d7fecb2 make subject hidden when none 2017-02-05 11:32:15 -05:00
Jeff Becker e6f6d4ef37 more 2017-02-05 11:30:26 -05:00
Jeff Becker eb369ca538 more 2017-02-05 11:21:56 -05:00
Jeff Becker ccefab982f more 2017-02-05 11:18:06 -05:00
Jeff Becker e800f9cfd0 more 2017-02-05 11:17:18 -05:00
Jeff Becker ac88b2e083 more 2017-02-05 11:16:28 -05:00
Jeff Becker 7749fb9ced more 2017-02-05 11:13:15 -05:00
Jeff Becker 2a6ee9bc23 more 2017-02-05 11:11:34 -05:00
Jeff Becker cbea6e011e make post.mustache cleaner 2017-02-05 11:09:59 -05:00
Jeff Becker 94632b37c9 initial chacha20 code; 2017-01-29 18:15:02 -05:00
Jeff Becker 21008c857a Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2017-01-29 17:21:52 -05:00
Jeff Becker 8521d0d490 Revert "Revert "add chacha20""
This reverts commit 2012e6d3a8.
2017-01-29 17:21:37 -05:00
Jeff 9e47a4f2c8 disable post reply 2017-01-29 16:15:01 -05:00
Jeff 7d556b0615 more fixes 2017-01-29 14:52:34 -05:00
Jeff Becker c5fa3ad4a2 try fixing escaping 2017-01-29 14:42:40 -05:00
Jeff 7c8129c42e Merge pull request #144 from wzeth/patch-20
remove pre-cambrian redis, add helpers
2017-01-29 11:44:38 -05:00
Jeff 4411538252 Merge pull request #145 from wzeth/patch-21
clarify TLS config
2017-01-29 11:44:09 -05:00
Jeff Becker 5ab54ae654 ammend flashy format 2017-01-29 10:32:16 -05:00
Jeff Becker f0790204c0 decrease flasy speed more 2017-01-29 10:27:33 -05:00
Jeff Becker c331570e37 decrease flasy speed 2017-01-29 10:26:48 -05:00
Jeff Becker 7ba642df36 increase flasy speed 2017-01-29 10:26:20 -05:00
Jeff Becker b29446bd9d add flashy text 2017-01-29 10:25:41 -05:00
Jeff Becker 836d1212cc make psytext use span 2017-01-29 10:21:05 -05:00
Jeff Becker 461721d729 make redtext use span 2017-01-29 10:20:44 -05:00
Jeff Becker 810c4f52fe add red text function 2017-01-29 10:12:43 -05:00
Jeff Becker b0c4dd5f66 move red text to lua formatting 2017-01-29 10:08:00 -05:00
Jeff Becker 4c6cfefdb5 exlode text align center 2017-01-29 10:02:17 -05:00
Jeff Becker 3d195510ba more escapes 2017-01-29 10:00:51 -05:00
Jeff Becker 6e5c34ebdd escape more in code tags 2017-01-29 09:52:05 -05:00
Jeff Becker 749e1fc069 try escaping pipe 2017-01-29 09:46:12 -05:00
Jeff Becker 3f6c6ed615 more 2017-01-29 09:34:18 -05:00
Jeff Becker af6c0ba6b8 fix 2017-01-29 09:31:52 -05:00
Jeff Becker f8acfaaae4 make smaller 2017-01-29 09:30:31 -05:00
Jeff Becker da43536e6c more formatting 2017-01-29 09:27:57 -05:00
wzeth f4ee1d3e0b clarify TLS config 2017-01-29 09:03:48 -05:00
wzeth c7be368be9 remove pre-cambrian redis, add helpers
Add some things someone might find useful, but that shouldn't be default:
* after network target
* require postgresql to start nntpchan
* setting `SRND_INI_PATH` if user would like to put their config elsewhere
2017-01-29 08:42:13 -05:00
Jeff Becker 3cb06d572e :-DDDD 2017-01-29 08:27:51 -05:00
Jeff Becker f94ecbdaa9 add psytext alias in lua 2017-01-28 15:12:00 -05:00
Jeff Becker f1f9ae33d9 add explode text 2017-01-28 14:39:31 -05:00
Jeff Becker 008cfb6db5 fix 2017-01-28 12:06:23 -05:00
Jeff Becker 46e8f48f66 try fixing wobble text 2017-01-28 11:46:32 -05:00
Jeff Becker 855c78a8f8 try fixing wobble text 2017-01-28 11:44:33 -05:00
Jeff Becker 9ec1c5c304 try fixing wobble text 2017-01-28 11:42:34 -05:00
Jeff Becker 0ab6dca181 center text in wobble 2017-01-28 11:36:00 -05:00
Jeff Becker 1d20cb3142 more 2017-01-28 11:29:57 -05:00
Jeff Becker baf6e29473 try fix 2017-01-28 10:49:45 -05:00
Jeff Becker 1346eb56ab fix parameters 2017-01-28 10:47:24 -05:00
Jeff Becker a8ac1dd67c Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2017-01-28 10:40:13 -05:00
Jeff Becker 0e51b675c2 add example lua stuff 2017-01-28 10:39:58 -05:00
Jeff 2fd58bebbb Merge pull request #143 from nilesr/master
Complete thunderbird-newsreader-configuration.md
2017-01-27 12:14:00 -05:00
Niles Rogoff f44430e3ca Bundled images 2017-01-27 11:24:03 -05:00
Niles Rogoff e705bbccba Complete thunderbird-newsreader-configuration.md 2017-01-27 00:12:35 -05:00
Jeff Becker a3ed5a9d91 add working varnish config 2017-01-26 20:56:58 -05:00
Jeff Becker 2012e6d3a8 Revert "add chacha20"
This reverts commit 90bf96a025.
2017-01-20 14:23:49 -05:00
Jeff Becker 90bf96a025 add chacha20 2017-01-20 13:29:52 -05:00
Jeff Becker da9e0d5808 css fix 2017-01-20 10:50:59 -05:00
Jeff Becker 99ebddc7c4 CURRENT YEAR 2017-01-18 19:17:29 -05:00
Jeff Becker baeabad1a4 fix 2017-01-18 14:07:49 -05:00
Jeff Becker 13724b751a bump 2017-01-18 14:03:59 -05:00
Jeff Becker cba3c29328 fix ignore 2017-01-18 14:02:06 -05:00
Jeff Becker 0e1e614696 bump gx version published 2017-01-18 14:00:13 -05:00
Jeff Becker 178b7e56f6 fix build and update gx 2017-01-18 13:59:22 -05:00
Jeff Becker 0feb319236 bump gx 2017-01-18 13:36:04 -05:00
Jeff Becker 4c927ff74a bump gx 2017-01-18 13:34:42 -05:00
Jeff Becker a5f3188cce track gx lastpubver 2017-01-18 13:21:56 -05:00
Jeff Becker 7cf55931b7 bump gx version 2017-01-18 13:16:32 -05:00
Jeff Becker 1174df8344 fix banner 2017-01-18 08:55:29 -05:00
Jeff Becker b41f1bebc8 add new banner 2017-01-18 08:45:58 -05:00
Jeff Becker ccb750679a more 2017-01-16 14:58:59 -05:00
Jeff Becker 5b4bcd7cd9 more 2017-01-16 14:57:58 -05:00
Jeff Becker a729848963 more 2017-01-16 14:55:37 -05:00
Jeff Becker 5727543e28 more 2017-01-16 14:54:38 -05:00
Jeff Becker e2f509641a more 2017-01-16 14:53:04 -05:00
Jeff Becker d000fcc993 more 2017-01-16 14:51:28 -05:00
Jeff Becker 52d401270f more 2017-01-16 14:49:32 -05:00
Jeff Becker 4d2d62681b more 2017-01-16 14:48:02 -05:00
Jeff Becker 3c61aad46c more 2017-01-16 14:47:37 -05:00
Jeff Becker 718863a2fc more 2017-01-16 14:47:00 -05:00
Jeff Becker 4d954861aa more 2017-01-16 14:46:10 -05:00
Jeff Becker aafe3ad2a8 more 2017-01-16 14:45:17 -05:00
Jeff Becker 0c15c22ca2 more 2017-01-16 14:43:25 -05:00
Jeff Becker ebf3f578b0 more 2017-01-16 14:42:07 -05:00
Jeff Becker c8146eb783 more 2017-01-16 14:41:24 -05:00
Jeff Becker 1b18fc89a2 more 2017-01-16 14:40:01 -05:00
Jeff Becker cfa83a7db8 more 2017-01-16 14:39:08 -05:00
Jeff Becker 8d6bd12346 more css 2017-01-16 14:33:44 -05:00
Jeff Becker 898bc668d9 try positioning 2017-01-16 14:32:11 -05:00
Jeff Becker 171d3e75f4 try positioning 2017-01-16 14:30:30 -05:00
Jeff Becker f04627ff4f try positioning 2017-01-16 14:30:05 -05:00
Jeff Becker c1c2ed2dda add to document 2017-01-16 14:24:33 -05:00
Jeff Becker 0fb9f392d7 fix types 2017-01-16 14:23:04 -05:00
Jeff Becker 7ac7399dcf prevent default 2017-01-16 14:21:59 -05:00
Jeff Becker 2885ebee81 add more logging 2017-01-16 14:20:46 -05:00
Jeff Becker ba5801f920 add more logging 2017-01-16 14:19:27 -05:00
Jeff Becker b65e0cdfba add logging 2017-01-16 14:17:43 -05:00
Jeff Becker 172b1e7c8c add reply box thing 2017-01-16 14:15:50 -05:00
Jeff Becker 0e8d277482 more 2017-01-16 13:23:46 -05:00
Jeff Becker 4be8c78aa7 more 2017-01-16 13:23:01 -05:00
Jeff Becker 3e178c63eb more 2017-01-16 12:08:52 -05:00
Jeff Becker 5cc2b1b937 more 2017-01-16 12:01:49 -05:00
Jeff Becker 997fad55e4 more 2017-01-16 12:01:22 -05:00
Jeff Becker 95b4dd7c91 more 2017-01-16 12:01:04 -05:00
Jeff Becker 4305692727 more 2017-01-16 12:00:46 -05:00
Jeff Becker 4665c0eb4e more 2017-01-16 11:59:12 -05:00
Jeff Becker 2aac424dc2 more 2017-01-16 11:58:44 -05:00
Jeff Becker e2d7846d45 more 2017-01-16 11:58:20 -05:00
Jeff Becker b42a2ae138 more 2017-01-16 11:57:57 -05:00
Jeff Becker 91476b700c more 2017-01-16 11:56:54 -05:00
Jeff Becker 13f8a0ab13 more 2017-01-16 11:55:16 -05:00
Jeff Becker 1467979dab more 2017-01-16 11:52:59 -05:00
Jeff Becker dfdf4043f1 more 2017-01-16 11:49:55 -05:00
Jeff Becker ba42a523ff more 2017-01-16 11:49:10 -05:00
Jeff Becker 49ef756672 more 2017-01-16 11:48:33 -05:00
Jeff Becker a97c3d7d48 more 2017-01-16 11:47:53 -05:00
Jeff Becker ad3089728a more 2017-01-16 11:42:37 -05:00
Jeff Becker bfd16332f1 more 2017-01-16 11:38:50 -05:00
Jeff Becker 9cf7e617cb idklol 2017-01-16 11:34:36 -05:00
Jeff Becker 12f8ee9131 don't inject post hover 2017-01-16 11:32:56 -05:00
Jeff Becker eabe6474de dyn reply fixes 2017-01-16 11:27:58 -05:00
Jeff Becker 75dc4c2529 fix syntax error 2017-01-16 11:23:04 -05:00
Jeff Becker 11b5ca6a1b re-enable dynamic reply 2017-01-16 11:21:45 -05:00
Jeff Becker 8c2ddda51a try fixing video expand 2017-01-16 11:11:56 -05:00
Jeff Becker 963637e750 try fixing expand video 2017-01-16 11:06:50 -05:00
Jeff Becker ff8bdcf08c more semicolons 2017-01-16 10:53:58 -05:00
Jeff Becker 6af49f6800 add semicolin 2017-01-16 10:52:46 -05:00
Jeff Becker f0a9a67c29 fix case 2017-01-16 10:35:44 -05:00
Jeff Becker 612c9c8989 fix case 2017-01-16 10:32:11 -05:00
Jeff Becker 026eaa2f84 fix report 2017-01-16 10:31:18 -05:00
Jeff Becker f229ea555c try fixing censortools 2017-01-16 10:21:37 -05:00
Jeff Becker aa29679a92 fix typo 2017-01-15 07:47:26 -05:00
Jeff Becker 97eec6053d update overview 2017-01-13 14:08:33 -05:00
Jeff Becker 64a78a4131 update ukko links to /o/ 2017-01-13 13:03:55 -05:00
Jeff Becker c8ca9dd855 increment banner count 2017-01-12 13:42:38 -05:00
Jeff Becker caddb84dfb add new banner 2017-01-12 13:41:49 -05:00
Jeff Becker f9d4d30941 more 2017-01-12 10:25:15 -05:00
Jeff Becker a09f1cd454 more 2017-01-12 09:59:29 -05:00
Jeff Becker 36c0bc127f :\ 2017-01-12 09:58:08 -05:00
Jeff Becker a36e523ddf more attempted fixes 2017-01-12 09:56:24 -05:00
Jeff Becker 992dfad0dc try fix for json 2017-01-12 09:54:21 -05:00
Jeff Becker 19452704fc fix id 2017-01-12 09:49:30 -05:00
Jeff Becker 953042578b fix css 2017-01-12 09:48:13 -05:00
Jeff Becker 01813b2877 update css 2017-01-12 09:47:14 -05:00
Jeff Becker 7096ea4e52 more 2017-01-12 09:44:59 -05:00
Jeff Becker 9e14d6ce30 :-DDDD 2017-01-12 09:40:33 -05:00
Jeff Becker 60d226c66b fug 2017-01-12 09:40:07 -05:00
Jeff Becker fc2c582627 fix js in censor tools 2017-01-12 09:38:48 -05:00
Jeff Becker 0eac006d52 more censortools changes 2017-01-12 09:37:23 -05:00
Jeff Becker 228af0c5f4 fix placement 2017-01-12 09:30:38 -05:00
Jeff Becker 0f60daf299 more censor tools stuff 2017-01-12 09:26:49 -05:00
Jeff Becker 1ec4663499 Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2017-01-12 09:25:05 -05:00
Jeff Becker 0e394ae25e add censortools to postform 2017-01-12 09:24:51 -05:00
jeff e818547661 fix urls 2017-01-10 14:07:51 -05:00
jeff 7e2d9f2d0f rename ukko to /overboard/ 2017-01-10 13:50:13 -05:00
Jeff Becker 25ae491ddc add more banners 2017-01-10 12:28:30 -05:00
Jeff Becker 5ef0085b57 more banners 2017-01-10 12:27:19 -05:00
Jeff Becker 536b1161c9 more 2016-12-31 08:36:28 -05:00
Jeff Becker e35adda727 semicolin 2016-12-27 11:08:59 -05:00
Jeff Becker ccbb348155 update search 2016-12-26 15:38:52 -05:00
Jeff Becker 1e81129090 add search by hash 2016-12-26 15:35:02 -05:00
Jeff Becker cbad613621 moar css 2016-12-26 12:08:10 -05:00
Jeff Becker 0d5fded584 moar css 2016-12-26 12:07:35 -05:00
Jeff Becker 595a258331 moar css 2016-12-26 12:06:35 -05:00
Jeff Becker d4305eb2f0 moar css 2016-12-26 12:05:14 -05:00
Jeff Becker 34559db9aa id -> class 2016-12-26 12:03:47 -05:00
Jeff Becker f275ceaec1 add css 2016-12-26 12:02:40 -05:00
Jeff Becker 0854260d43 fix 2016-12-26 11:48:45 -05:00
Jeff Becker 6f8862b631 fix 2016-12-26 11:48:00 -05:00
Jeff Becker 69c20952ad more 2016-12-26 11:46:27 -05:00
Jeff Becker ada1a614ea update link to use new tab 2016-12-26 11:43:46 -05:00
Jeff Becker b0ede42c61 fix query 2016-12-26 11:34:57 -05:00
Jeff Becker c9f5cf183c update search 2016-12-26 11:33:51 -05:00
Jeff Becker e9e94b17d5 bug fix 2016-12-26 11:26:24 -05:00
Jeff Becker 23390b5998 fix 2016-12-26 11:24:30 -05:00
Jeff Becker 8f9622dca8 update search 2016-12-26 11:21:34 -05:00
Jeff Becker 579970c079 more 2016-12-26 10:11:29 -05:00
Jeff Becker 000fb43159 ebin 2016-12-20 11:07:52 -05:00
Jeff Becker 78e7895c70 Revert "Revert "update templates and shit""
This reverts commit f5520a7127.
2016-12-14 17:45:48 -05:00
Jeff Becker 82a0746d3e Revert "Revert "Revert "update templates and shit"""
This reverts commit 2b811a6b34.
2016-12-14 17:45:48 -05:00
Jeff Becker b5580bebdd Revert "Revert "Revert "Revert "update templates and shit""""
This reverts commit fc1e20bd6f.
2016-12-14 17:45:47 -05:00
Jeff Becker e672f412dc Revert "Revert "Revert "update templates and shit"""
This reverts commit a86345aa8b.
2016-12-14 17:45:47 -05:00
Jeff Becker bdf11b535c Revert "Revert "fix build.sh""
This reverts commit f319d8e809.
2016-12-14 17:45:47 -05:00
Jeff Becker 2468083ba2 Revert "Revert "update build.sh""
This reverts commit 38354318b8.
2016-12-14 17:45:46 -05:00
Jeff Becker a00a902022 Revert "Revert "move nntpchand source to nntpchan repo""
This reverts commit 1465b99df6.
2016-12-14 17:45:44 -05:00
Jeff Becker 1465b99df6 Revert "move nntpchand source to nntpchan repo"
This reverts commit 91406d3400.
2016-12-14 17:40:58 -05:00
Jeff Becker 38354318b8 Revert "update build.sh"
This reverts commit c0ae3d0756.
2016-12-14 17:40:58 -05:00
Jeff Becker f319d8e809 Revert "fix build.sh"
This reverts commit a93f3201f9.
2016-12-14 17:40:58 -05:00
Jeff Becker a86345aa8b Revert "Revert "update templates and shit""
This reverts commit f5520a7127.
2016-12-14 17:40:56 -05:00
Jeff Becker fc1e20bd6f Revert "Revert "Revert "update templates and shit"""
This reverts commit 2b811a6b34.
2016-12-14 17:40:50 -05:00
Jeff Becker 2b811a6b34 Revert "Revert "update templates and shit""
This reverts commit f5520a7127.
2016-12-14 17:40:39 -05:00
Jeff Becker f5520a7127 Revert "update templates and shit"
This reverts commit 8dd77dcdf0.
2016-12-14 17:40:13 -05:00
Jeff Becker a93f3201f9 fix build.sh 2016-11-18 09:58:15 -05:00
Jeff Becker c0ae3d0756 update build.sh 2016-11-18 09:57:24 -05:00
Jeff Becker 91406d3400 move nntpchand source to nntpchan repo 2016-11-18 09:54:13 -05:00
Jeff Becker 8dd77dcdf0 update templates and shit 2016-11-17 16:42:15 -05:00
Jeff Becker 3ab022f45d add unstaged changes 2016-11-16 11:38:03 -05:00
Jeff Becker c677cebde5 more, add initial mod ui 2016-11-16 10:19:00 -05:00
Jeff Becker 6f01bac76c fix hook more 2016-11-15 09:00:51 -05:00
Jeff Becker c0e216a390 fix hook again 2016-11-15 08:58:59 -05:00
Jeff Becker 2527e695dd update hooks 2016-11-15 08:52:55 -05:00
Jeff Becker fdedd6a6c0 fix hook 2016-11-15 08:51:57 -05:00
Jeff Becker 59c52f775f add purge varnish hook (initial) 2016-11-15 08:49:54 -05:00
Jeff Becker c8cb42edfd off by one 2016-11-12 13:08:43 -05:00
Jeff Becker 4ad781e541 fix index out of bounds 2016-11-12 13:06:40 -05:00
Jeff Becker 4f0c2e2f18 Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2016-11-12 09:06:35 -05:00
Jeff Becker 6065eca82f update style for torbb 2016-11-12 09:06:18 -05:00
Jeff 3983506fe3 Update moderation.md 2016-11-10 15:19:14 -05:00
Jeff Becker 4ea96b155f don't use imgur 2016-11-10 15:14:17 -05:00
Jeff Becker 3429ac63f8 add docs on moderation from anon 2016-11-10 15:11:09 -05:00
Jeff Becker 2ae4f2268b make posting work 2016-11-10 08:46:01 -05:00
Jeff Becker 801272ae7d provide url for ctl 2016-11-09 15:12:46 -05:00
Jeff Becker d1a81f319d make mod backend work 2016-11-09 14:32:26 -05:00
Jeff Becker 9f7de85a1f remove unneeded template 2016-11-09 12:24:59 -05:00
Jeff Becker 518a32016b add initial censor ui 2016-11-09 12:22:22 -05:00
Jeff Becker e036db805e more 2016-11-08 07:22:43 -05:00
Jeff Becker 56b90bf5f7 * add captcha reloader
* update posted template
2016-11-08 06:49:52 -05:00
Jeff Becker 6cdcc4c3b9 fixes 2016-11-07 13:31:57 -05:00
Jeff Becker 487495f9ac update op when we get it 2016-11-07 13:24:33 -05:00
Jeff Becker 15bc796952 case insensative file extensions 2016-11-07 12:52:28 -05:00
Jeff Becker 774b2a5e50 update bump logic 2016-11-07 12:42:26 -05:00
Jeff Becker 78dccbfd61 make secret_key "changeme" by default to encourage people to change it 2016-11-07 09:56:58 -05:00
Jeff Becker 6eefd675e6 add forgotten files 2016-11-07 09:52:21 -05:00
Jeff Becker 3fed1d8d41 more 2016-11-07 09:52:00 -05:00
Jeff Becker 7a4c875fd5 update url for front page 2016-11-07 09:12:31 -05:00
Jeff Becker f315823dcd update url rules 2016-11-07 09:10:24 -05:00
Jeff Becker 64a9e471ef fix regression 2016-11-07 09:04:55 -05:00
Jeff Becker 670f613596 update page logic, don't use queries for page numbers 2016-11-07 09:03:11 -05:00
Jeff Becker 84092c979f add example config for nginx+varnish 2016-11-07 08:39:35 -05:00
Jeff Becker 3fad9794da add default varnish config 2016-11-07 08:20:04 -05:00
Jeff Becker ecf8237c97 update settings and add readme 2016-11-07 07:50:10 -05:00
Jeff Becker c3224379ca more 2016-11-07 07:02:03 -05:00
Jeff Becker 2a744c45a2 fix making new threads 2016-11-06 17:55:02 -05:00
Jeff Becker 64b345a7f0 fix message 2016-11-06 17:50:13 -05:00
Jeff Becker f25f2cd956 it now works 2016-11-06 17:47:23 -05:00
Jeff Becker 14c68abf9d more 2016-11-06 16:01:05 -05:00
Jeff Becker 3c2da5f25b don't hardcode media url in attachments 2016-11-06 11:21:37 -05:00
Jeff Becker dafa5ca517 make pagination work 2016-11-06 11:17:46 -05:00
Jeff Becker d81e709827 correct bump order for board page 2016-11-06 11:01:04 -05:00
Jeff Becker 4c7dd44815 make images open in new tab 2016-11-06 10:58:19 -05:00
Jeff Becker 514064ce5a update supported thumbnail types 2016-11-06 10:50:12 -05:00
Jeff Becker dac258a978 remove recursive fun for markup filter 2016-11-06 10:49:57 -05:00
Jeff Becker a9860d82ba various fixes 2016-11-06 10:20:03 -05:00
Jeff Becker cc957f3de5 * fix thumbnailing
* make thumbnailing programs configurable
2016-11-06 08:08:34 -05:00
Jeff Becker 8665b98452 fix thumbnails 2016-11-06 08:00:18 -05:00
Jeff Becker 31a12185f6 more fixes 2016-11-05 16:15:41 -04:00
Jeff Becker e686f0d57e more 2016-11-05 14:58:28 -04:00
Jeff Becker 8ffc8c006c more 2016-11-05 14:54:22 -04:00
Jeff Becker a19d36f883 more 2016-11-04 16:51:25 -04:00
Jeff Becker 3aa87e07f2 update 2016-11-04 09:01:17 -04:00
Jeff Becker be4fbda2a6 more 2016-11-04 09:00:03 -04:00
Jeff Becker 7f25dcf95c broken 2016-11-04 08:45:06 -04:00
Jeff Becker a7e33a9f10 add gitignore 2016-11-04 07:31:03 -04:00
Jeff Becker 2c49987c6d add base django stuff 2016-11-04 07:28:25 -04:00
Jeff 00fa6eb561 Merge pull request #141 from wzeth/patch-19
set explicit height and width for captcha
2016-11-02 17:34:43 -04:00
Jeff 9d18d59f45 Merge pull request #142 from wzeth/patch-18
explicitly set height and width attrs to avoid jumping beans
2016-11-02 17:33:52 -04:00
Jeff Becker f47b181290 fix captcha reload for ukko page 2016-11-02 16:18:12 -04:00
Jeff Becker 6d7f2bd587 add pagination at bottom of ukko 2016-11-02 16:13:11 -04:00
Jeff Becker 3bc2befb88 finish burst of commits 2016-11-02 16:11:43 -04:00
Jeff Becker 239ba55f1f more 2016-11-02 16:09:43 -04:00
Jeff Becker 349c588bdd more 2016-11-02 16:07:28 -04:00
Jeff Becker 4bd8f0a688 more 2016-11-02 16:05:50 -04:00
Jeff Becker 6b3fc260a6 more 2016-11-02 16:04:19 -04:00
Jeff Becker 975693d241 more 2016-11-02 16:03:49 -04:00
Jeff Becker 6b934ebd52 more 2016-11-02 16:02:58 -04:00
Jeff Becker 95ab7448be idunno 2016-11-02 15:58:43 -04:00
Jeff Becker 1acad1b11f fix 2016-11-02 15:58:12 -04:00
Jeff Becker 4d91cbd084 fix 2016-11-02 15:56:59 -04:00
Jeff Becker 89d20a1617 fix typo 2016-11-02 15:56:07 -04:00
Jeff Becker 20120a8690 more 2016-11-02 15:54:27 -04:00
Jeff Becker 864a751130 more 2016-11-02 15:50:53 -04:00
Jeff Becker e668cdc16e more 2016-11-02 15:45:30 -04:00
Jeff Becker f76ba6422c fix 2016-11-02 15:44:01 -04:00
Jeff Becker 9a6400e15b more 2016-11-02 15:42:53 -04:00
Jeff Becker a068fe634d fix css a bit 2016-11-02 15:41:39 -04:00
Jeff Becker a5da6d2e78 fix 2016-11-02 15:33:53 -04:00
Jeff Becker e32f60e658 more 2016-11-02 15:33:06 -04:00
Jeff Becker 21b5a21008 tweaks 2016-11-02 15:28:48 -04:00
Jeff Becker 4ada177ae9 more fixes 2016-11-02 15:24:51 -04:00
Jeff Becker 176c162781 fix ukko formatting 2016-11-02 15:23:23 -04:00
Jeff Becker d77b2dbff9 fix missing div 2016-11-02 15:17:14 -04:00
Jeff Becker 6bb2b154ef add truncation info to ukko 2016-11-02 14:33:58 -04:00
Jeff Becker 83cc63fc06 give more info about truncation in board template 2016-11-02 14:29:12 -04:00
Jeff Becker 89a004e8ec fix 2016-11-02 11:23:17 -04:00
Jeff Becker b393c066b0 fix 2016-11-02 11:22:18 -04:00
Jeff Becker 2eecfeafaa fix typo 2016-11-02 11:21:14 -04:00
Jeff Becker 25a15100a9 fix 2016-11-02 11:19:45 -04:00
Jeff Becker aeab87cb51 fix search 2016-11-02 11:18:11 -04:00
Jeff Becker 458a1c04d9 add search page 2016-11-02 11:16:31 -04:00
wzeth af4baa42a4 set explicit height for captcha
Now less bean jumping and more meme having.
2016-11-02 09:06:28 -04:00
wzeth d64be9150d fix the jumping beans effect
Pages will jump if image size isn't explicitly declared.
2016-11-02 09:01:38 -04:00
Jeff Becker 4be03b0b96 add nntpchan nginx config for no prefix 2016-11-02 08:44:05 -04:00
Jeff Becker b34b58a0cf fix 2016-10-31 11:05:47 -04:00
Jeff Becker d52c65828f Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2016-10-31 10:55:18 -04:00
Jeff Becker 26a21fe6bf add paginated ukko links 2016-10-31 10:55:03 -04:00
Jeff 030460e2c4 Merge pull request #140 from wzeth/patch-17
Add building instructions for Ubuntu 16.10
2016-10-27 09:25:02 -04:00
wzeth 84cdf459ae fix typo
depencies :DDDDD
2016-10-27 03:06:57 -04:00
wzeth 190321b4c4 Rename building-ubuntu16.10 to building-ubuntu16.10.md 2016-10-27 03:00:42 -04:00
wzeth 37119a249e Create building-ubuntu16.10 2016-10-27 02:59:36 -04:00
Jeff Becker 2caf487c72 add logo to readme 2016-10-25 10:01:07 -04:00
Jeff Becker aecb4b6ac0 add logo 2016-10-25 10:00:10 -04:00
Jeff Becker 554d2d753e update readme again 2016-10-25 09:55:54 -04:00
Jeff Becker 13739363f4 update readme to point users to nntpchan.info 2016-10-25 09:54:45 -04:00
Jeff Becker 00fdbb9449 Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2016-10-22 15:43:48 -04:00
Jeff Becker 4369765253 backlog for mod feed 2016-10-22 15:28:35 -04:00
Jeff 9883ed4396 Merge pull request #139 from wzeth/patch-16
deprecate redis
2016-10-20 16:23:49 -04:00
wzeth ba7140053a remove --createdb and upgrade go version
--createdb doesn't always work for some reason, so prefer the `createdb srnd` command instead. Upgrade to go 1.7.3 because, as far as I know, SRNDv2 compiles on this version.
2016-10-20 12:51:06 -04:00
wzeth 2727fe9dff deprecate redis
redis is trash kill you'reself
2016-10-20 12:44:13 -04:00
Jeff Becker e080e939dd Revert "switch to typescript"
This reverts commit de5883d0a0.
2016-10-18 10:30:32 -04:00
Jeff Becker 4b1da71030 Revert "add more stuff"
This reverts commit 2aa79bd014.
2016-10-18 10:30:32 -04:00
Jeff Becker 2aa79bd014 add more stuff 2016-10-18 09:32:00 -04:00
Jeff Becker de5883d0a0 switch to typescript 2016-10-18 09:03:46 -04:00
Jeff Becker ce3919fc1f update nntpchan python frontend 2016-10-18 08:46:22 -04:00
Jeff Becker 561a0156be add --enable-redis flag 2016-10-18 08:44:15 -04:00
Jeff Becker fde7ed3d3b more 2016-10-18 08:17:40 -04:00
Jeff Becker 3c4ad2fe50 disable neochan by default 2016-10-18 07:08:49 -04:00
Jeff Becker cd803852e7 add vendor 2016-10-18 07:05:34 -04:00
Jeff Becker 2e2968e188 Merge branch 'neochan' 2016-10-18 07:04:21 -04:00
Jeff Becker 4f3bc5cf6e more recent changes 2016-10-18 07:03:51 -04:00
Jeff Becker 378a257377 move 2016-10-16 07:05:57 -04:00
Jeff Becker 04df5de9a1 fix 2016-10-15 13:55:25 -04:00
Jeff Becker 9ae0b0ef5b updates 2016-10-15 13:53:35 -04:00
Jeff Becker d31ca5b6a7 update dis shit mang 2016-10-15 12:37:59 -04:00
Jeff Becker cc089b3401 track primordial goo frontends 2016-10-15 09:12:01 -04:00
Jeff Becker 7b8d33826b initial neochan commit 2016-10-15 09:05:38 -04:00
Jan Verbeek 9e9a1efe06 Merge https://gitgud.io/uguu/nntpchan
Conflicts:
	build-js.sh
	build.sh
2016-10-08 14:29:46 +02:00
Jeff Becker a5d7cb9074 Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2016-10-08 08:12:37 -04:00
Jeff 053b5870cf Merge pull request #138 from wzeth/patch-15
Explicit notice of redis cache deprecation
2016-10-08 08:09:59 -04:00
wzeth 4ab90f3152 Explicit notice of redis cache deprecation
Users should know that redis cache is no longer valid as of SRNDv2 commit 96de42
2016-10-08 05:08:46 -04:00
Jeff Becker dc75a3513e add js branding 2016-10-07 10:17:29 -04:00
Jeff Becker 40ceb747ae refactor structure 2016-10-07 10:06:25 -04:00
Jeff Becker 6996e3abc4 remove cuckhold pow in postform 2016-10-07 08:26:50 -04:00
Jeff Becker 5118ffb3f8 fix tomorrow.css 2016-10-07 07:36:33 -04:00
Jeff Becker 287a49f196 fix tomorrow.css 2016-10-07 07:35:06 -04:00
Jeff Becker 698ed1d42e previous commit 2016-10-07 07:34:08 -04:00
Jeff Becker a0deb532e3 fix bloodgod.css moar 2016-10-07 07:33:03 -04:00
Jeff Becker 0e1e6201ca fix bloodgod.css 2016-10-07 07:30:29 -04:00
Jeff Becker 6ea75236fa fix post.mustache 2016-10-07 07:25:30 -04:00
Jeff Becker 61281190bb disable feature 2016-10-07 07:24:00 -04:00
Jeff Becker 2355528b46 fug 2016-10-02 20:42:45 -04:00
Jeff Becker db5b8ec309 try fixing liveui for chrome 2016-10-02 20:36:59 -04:00
Jeff Becker a0a0a6feca update readme 2016-10-02 09:01:58 -04:00
Jeff 787bef7625 Merge pull request #134 from wzeth/patch-13
Use more succinct postgres role creation command
2016-09-10 10:21:08 -04:00
wzeth e57d4ea921 Use more succinct postgres role creation command
It is far less error prone to use the tools that Postgres provides to create the role and the database. This amendment also ensures the created role password is encrypted.
2016-09-10 09:34:00 -04:00
Jeff c6c9c3f53b apply mona's css patch 2016-09-06 19:05:52 -04:00
Jeff Becker f7eb634aa1 fix :p 2016-08-14 11:27:46 -04:00
Jeff Becker 74f07c3a6c add test file 2016-08-14 11:26:07 -04:00
Jeff Becker 95864559fb wrap post in pre tag 2016-08-02 20:03:45 -04:00
Jeff Becker 5155205e8c indent 2016-08-01 07:34:35 -04:00
Jeff Becker d91b0d3e99 Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2016-08-01 07:24:43 -04:00
Jeff Becker 3df355abdb update banners 2016-08-01 07:24:25 -04:00
Jeff Becker 850e5bccae fix css 2016-07-30 08:03:32 -04:00
Jeff Becker 713fe21190 comiit changes 2016-07-30 08:02:05 -04:00
Jeff 3d683ab87e Merge pull request #131 from deavmi/patch-1
Update building.md
2016-07-22 06:24:50 -04:00
Tristan B. Kildaire a4053f0f1a Update building.md 2016-07-21 20:57:04 +02:00
Jeff 87e29cc117 Merge pull request #129 from deavmi/patch-1
Various fixes
2016-07-19 19:16:11 -04:00
Tristan B. Kildaire c17d0fb0bb Various fixes
* Added missing period.
* Fixed typo.
2016-07-19 22:46:22 +02:00
Jeff Becker 985863deb2 add fade to post hide/unhide 2016-07-18 11:12:47 -04:00
Jeff Becker a9d2c0425d have post hiding persist in localstorage 2016-07-18 10:44:18 -04:00
Jeff Becker 76cb2341ce add hr to post for reply hider 2016-07-18 09:59:53 -04:00
Jeff Becker ceb6f09a3f update 2016-07-18 09:50:40 -04:00
Jeff Becker adf3540556 * add hide-post.js
* disable cuckoo_miner.js
2016-07-18 09:49:44 -04:00
Jeff Becker 2ce8a38b0b update css 2016-07-18 08:26:41 -04:00
Jeff Becker e62d959b0b remove title from post no 2016-07-18 08:17:48 -04:00
Jeff Becker 4216a777a3 fix name field in post.mustache 2016-07-18 08:13:27 -04:00
Jeff Becker 5873b41e00 add hr to separate post header from post body 2016-07-18 08:11:10 -04:00
Jeff Becker 14635e9472 have postreply class float right 2016-07-18 08:08:03 -04:00
Jeff Becker 422f3de11d add postreply class to div for future css 2016-07-18 08:04:58 -04:00
Jeff Becker 64b5531fed change post.mustache format to be "better" 2016-07-18 08:02:42 -04:00
Jeff Becker 17f3b25e51 fixes 2016-07-18 07:57:25 -04:00
Jeff Becker 60f0c19a9f update all 2016-07-18 07:51:15 -04:00
Jeff Becker f4f2479b8a fix 2016-07-17 11:34:39 -04:00
Jeff Becker 3506d7f975 try fixing liveui 2016-07-17 11:28:49 -04:00
Jeff Becker 9acca366d0 livechan post via ajax not websocket 2016-07-17 11:23:15 -04:00
Jeff Becker 70fd791545 fix 2016-07-13 09:17:20 -04:00
Jeff Becker 9f3c41fb0b more theme tweaks 2016-07-13 09:16:34 -04:00
Jeff Becker 2ff6088605 fix typo 2016-07-13 09:15:39 -04:00
Jeff Becker 54644e0da2 more theme updates / unborking 2016-07-13 09:14:39 -04:00
Jeff Becker dbd05c30c3 update dayman theme 2016-07-13 09:02:26 -04:00
Jeff Becker 587cdf4e75 fix tomorrow theme 2016-07-13 09:00:24 -04:00
Jeff Becker 76d75b260f update css for livechan 2016-07-11 14:48:33 -04:00
Jeff Becker 35ff3759f4 revert 2016-07-10 07:07:36 -04:00
Jeff Becker 671db6e483 update livechan.js 2016-07-10 07:05:19 -04:00
Jeff Becker 32566bfd84 fixes for liveui 2016-07-09 15:39:35 -04:00
Jeff Becker 4b02ad6d89 don't default to random, default to ukko 2016-07-09 14:51:31 -04:00
Jeff Becker a5c2f8d86f update livechan for ukko view 2016-07-09 14:48:06 -04:00
Jeff Becker 6e1e7440dc update livechan css 2016-07-08 08:55:09 -04:00
Jeff Becker 0b460eeb5d fix css 2016-07-08 08:52:10 -04:00
Jeff Becker 2a32bb75d5 fix captcha css 2016-07-08 08:50:31 -04:00
Jeff Becker cf91d8ffa5 Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2016-07-08 08:48:10 -04:00
Jeff Becker 375713390e switch livechan.css to use dark theme 2016-07-08 08:47:46 -04:00
Jeff f823b0e612 Merge pull request #127 from deavmi/patch-1
Update srnd.md
2016-07-07 19:29:25 -04:00
Tristan B. Kildaire cb1821189a Update srnd.md 2016-07-07 19:04:19 +02:00
Jeff Becker 1a5862213c Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2016-07-06 13:37:13 -04:00
Jeff Becker 96c019324d update ukko template to point livechan link to livechan 2016-07-06 13:36:50 -04:00
Jeff 1e905b6bbf Merge pull request #126 from wzeth/patch-12
update definitions for allow_anon*
2016-07-06 12:40:45 -04:00
wzeth 7c6726b5fc update definitions for allow_anon*
I have 40% confidence this is correct :v)
2016-07-06 12:35:34 -04:00
Jeff Becker 24d18ff599 hide captcha by default 2016-07-06 08:12:56 -04:00
Jeff Becker 16d0489cd7 don't show captcha on first start 2016-07-06 08:05:31 -04:00
Jeff Becker 5875347966 focus on new threads in liveui 2016-07-06 07:59:13 -04:00
Jeff Becker b2c1d9eb26 unscrewup reconnect 2016-07-05 20:43:36 -04:00
Jeff Becker a0bc39aaa5 expire old convos 2016-07-05 19:22:08 -04:00
Jeff Becker b887d07172 default to overchan.random for livechan 2016-07-05 17:46:34 -04:00
Jeff Becker 1f48c58f6b fix css for livechan file input 2016-07-05 17:39:40 -04:00
Jeff Becker e8eec5862f lower padding for chat input widget 2016-07-05 13:09:56 -04:00
Jeff Becker bf7213bf09 position fixed 2016-07-05 12:59:36 -04:00
Jeff Becker b2201c4ef7 add subjects 2016-07-05 12:58:13 -04:00
Jeff Becker a4747b9965 various fixes 2016-07-05 12:45:28 -04:00
Jeff Becker 5ec4c823fe fix css for firefox 2016-07-05 12:28:37 -04:00
Jeff Becker 00d0be952f position fixed 2016-07-05 12:19:40 -04:00
Jeff Becker c448777fe9 update livechan template 2016-07-05 12:16:32 -04:00
Jeff Becker 30b54c17fa document -> document.body 2016-07-05 12:14:52 -04:00
Jeff Becker e954c57da6 fix up livechan template 2016-07-05 12:13:48 -04:00
Jeff Becker d5d30893e5 livechan fixes 2016-07-05 10:11:58 -04:00
Jeff Becker 72947dbbcc update livechan to be aware of convos 2016-07-05 09:53:23 -04:00
Jeff Becker 1c632666ab update livechan 2016-07-05 08:17:19 -04:00
Jeff Becker 5cf12f37a5 meh this should work for livechan ui 2016-07-04 15:48:40 -04:00
Jeff Becker 9c038021b5 update rollover in livechan 2016-07-04 12:50:00 -04:00
Jeff Becker 4a8861761d update livechan to allow attachments 2016-07-04 11:52:43 -04:00
Jeff Becker 13e0010419 update rollover in livechan ui 2016-07-04 11:28:10 -04:00
Jeff Becker e461462bd6 actually fix thumbnails 2016-07-04 10:43:08 -04:00
Jeff Becker 8101e67b10 fix thumbnailing 2016-07-04 10:40:09 -04:00
Jeff Becker 63edd14243 fix date error 2016-07-04 10:36:10 -04:00
Jeff Becker d2142f7c83 Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2016-07-04 10:13:52 -04:00
Jeff Becker 28b1864841 add new livechan ui 2016-07-04 10:12:03 -04:00
Jeff 5fa1e76971 Merge pull request #125 from wzeth/patch-11
document archive in [nntp]
2016-07-04 07:16:14 -04:00
wzeth 40eeb116de document archive in [nntp] 2016-07-04 02:27:56 -04:00
ring a502259ba9 Quote variables, remove trailing whitespace
If you don't quote your variables the scripts get very buggy if you run
them with arguments with spaces in them, or even run them from a
directory with spaces in its path.
2016-07-02 23:30:03 +02:00
Jeff cac18a5e44 Merge pull request #124 from deavmi/master
Update README.md
2016-07-02 08:32:25 -04:00
Tristan B. Kildaire c86f573440 Update README.md 2016-07-02 14:15:59 +02:00
Jeff Becker 6f5130d8fd Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2016-06-30 09:01:31 -04:00
Jeff Becker 17b8101349 update livechan.js and stylesheets 2016-06-30 09:01:11 -04:00
Jeff 5e53ae6f04 Merge pull request #122 from deavmi/patch-1
Can I put this here?
2016-06-30 06:50:12 -04:00
Tristan B. Kildaire 50c395aad4 Update TODO.md 2016-06-30 12:48:05 +02:00
Jeff 18bf12e556 Merge pull request #118 from deavmi/patch-2
Create thunderbird-newsreader-configuration.md
2016-06-30 06:46:19 -04:00
Jeff bc1c038468 Merge pull request #117 from deavmi/patch-1
Create pan-newsreader-configuration.md
2016-06-30 06:46:08 -04:00
Jeff 7117a25f9a Merge pull request #116 from deavmi/patch-3
Update configure-newsreader.md
2016-06-30 06:45:50 -04:00
Jeff ef69bda0d7 Merge pull request #120 from deavmi/patch-5
Update README.md
2016-06-30 06:45:36 -04:00
Jeff ab6ac43851 Merge pull request #121 from deavmi/patch-6
Update README.md
2016-06-30 06:45:28 -04:00
Jeff 28feb5a84e Merge pull request #119 from deavmi/patch-4
Update fr-FR.ini
2016-06-30 06:44:26 -04:00
Tristan B. Kildaire 9e3e0cc443 Update README.md 2016-06-30 11:40:19 +02:00
Tristan B. Kildaire c573fb646b Update README.md 2016-06-30 11:37:47 +02:00
Tristan B. Kildaire 93b3e0f83f Update fr-FR.ini 2016-06-30 11:35:23 +02:00
Tristan B. Kildaire 7dda235ab1 Update configure-newsreader.md 2016-06-30 11:32:39 +02:00
Tristan B. Kildaire 09e7969479 Create thunderbird-newsreader-configuration.md 2016-06-30 11:32:37 +02:00
Tristan B. Kildaire cb37a45b67 Create pan-newsreader-configuration.md 2016-06-30 11:32:36 +02:00
Jeff Becker e25d6ab370 remove unneeded css rule 2016-06-20 15:11:05 -04:00
Jeff Becker e2194d3fbd fix css so that inline expand of images works 2016-06-20 13:05:36 -04:00
Jeff fdc4234d08 Merge pull request #113 from wzeth/patch-9
document feeds.d
2016-06-20 12:58:06 -04:00
wzeth 0c0160da6d Update srnd.md 2016-06-20 11:21:46 -04:00
wzeth fd82218e5f doucment feeds.d 2016-06-20 11:18:19 -04:00
Jeff Becker 091d74af52 Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2016-06-20 09:38:10 -04:00
Jeff Becker e690b7dd9c add feeds.d directory 2016-06-20 09:37:57 -04:00
Jeff a856af693f Merge pull request #112 from wzeth/patch-8
document SRND_FEEDS_INI_PATH environment variable
2016-06-20 07:47:24 -04:00
Jeff 3668eb7822 Merge pull request #111 from wzeth/patch-7
document SRND_INI_PATH environment variable
2016-06-20 07:47:09 -04:00
wzeth 3cc04a6cad document SRND_FEEDS_INI_PATH environment variable 2016-06-20 10:09:24 +00:00
wzeth e6967a75e7 document custom config locations 2016-06-20 09:59:03 +00:00
Jeff 679ee50342 Merge pull request #109 from wzeth/patch-6
clarified anon_nntp and pprof
2016-06-19 07:00:18 -04:00
wzeth b73c219e6b clarified anon_nntp and pprof 2016-06-19 01:12:33 -04:00
Jeff 1b474af875 Merge pull request #108 from wzeth/patch-5
document frontend minimize_html feature
2016-06-17 11:09:28 -04:00
wzeth 77a72c5770 document frontend minimize_html feature 2016-06-17 12:51:00 +00:00
Jeff Becker a52fe21743 add id='current_theme' to fix board list css themes not applying 2016-06-16 16:18:59 -04:00
Jeff Becker 42c70990a0 update bloodgod.css, thanks ano^ 2016-06-16 16:12:54 -04:00
Jeff 0980903b6e Merge pull request #106 from wzeth/patch-4
Debian 8.5 install guide
2016-06-15 08:44:17 -04:00
wzeth 47737dd205 Update building-debian8.5.md
set a title and backtick some directories and commands
2016-06-15 10:33:10 +00:00
wzeth a22330f920 added links to the setup guide 2016-06-15 10:30:51 +00:00
wzeth 05b4695398 Update and rename debian8.5-step-by-step.md to building-debian8.5.md
Made things a little more concise. I removed ffmpeg in favor of libav-tools because it is available in the default repositories.
2016-06-15 10:19:43 +00:00
Jeff Becker 415fb3c4a8 merge 2016-06-14 22:37:41 -04:00
Jeff Becker 5138c31e58 update node list 2016-06-14 22:37:22 -04:00
Jeff 052259c9d1 Merge pull request #105 from wzeth/patch-3
add missing command
2016-06-13 11:47:11 -04:00
wzeth 7276e28bb7 add missing command 2016-06-13 02:21:57 -04:00
Jeff Becker 2adf2d5127 update 2016-06-12 14:19:07 -04:00
Jeff Becker 242094193f fix typo 2016-06-12 13:55:07 -04:00
Jeff Becker 2ffc7a80e6 update css 2016-06-12 13:54:31 -04:00
Jeff Becker 3da1ab157d update css 2016-06-12 13:52:24 -04:00
Jeff Becker 17d2654f26 update css 2016-06-12 13:50:38 -04:00
Jeff Becker f155b0e9a1 update style 2016-06-12 13:46:28 -04:00
Jeff Becker c97296700f include gchan.xyz in node list 2016-06-12 12:38:08 -04:00
Jeff 3951432bad Merge pull request #104 from wzeth/patch-2
Step-by-step for Debian 8.5
2016-06-12 08:25:08 -04:00
Jeff da5c44d4fd Merge pull request #103 from wzeth/patch-1
SystemD Service
2016-06-12 08:24:59 -04:00
wzeth a35889ca18 Step-by-step for Debian 8.5
This will help users with a step-by-step guide to installing. I will try to make this into a script or something one day.
2016-06-12 06:27:53 -04:00
wzeth c171e62d52 oops made a typo 2016-06-12 05:37:19 -04:00
wzeth 75a3cf5ede systemd service file for nntpchan
Assumptions made:
1. The user has a redis_6379.service
2. The user is using /opt/nntpchan as the working directory for the srndv2
2016-06-12 05:36:05 -04:00
wzeth 2d25b349f7 Oops wrong dir 2016-06-12 05:34:59 -04:00
wzeth 29149eb452 Systemd service file
Here is an example systemd config.

It makes some assumptions:
1. The user has a systemd service called redis_6379.service (the redis install utils have this as default).
2. srndv2 is contained in /opt/nntpchan
2016-06-12 05:29:43 -04:00
Jeff 57232aeaf0 Merge pull request #102 from deavmi/patch-1
Previous link was broken but I have a new link.
2016-06-10 17:53:05 -04:00
Tristan B. Kildaire 2ced2b73c7 Previous link was broken but I have a new link. 2016-06-10 20:45:36 +02:00
Jeff 0dce01cd6d Merge pull request #101 from deavmi/patch-1
Bug fix.
2016-06-09 11:12:10 -04:00
Tristan B. Kildaire 5d05f62db5 Bug fix. 2016-06-09 07:17:53 +02:00
Jeff Becker fe9de25dcd remove .trash directory 2016-06-05 15:48:11 -04:00
Jeff 2c2bfce762 Merge pull request #100 from deavmi/master
Minor imporvements
2016-06-05 14:47:05 -04:00
Tristan B. Kildaire (Mobile) 68bc36c0db 2016-06-05 17:53:47 +02:00
Jeff 5c353e94f0 Merge pull request #97 from deavmi/patch-2
Update README.md
2016-06-05 08:01:31 -04:00
Tristan B. Kildaire d1d2ade366 Update README.md 2016-06-05 14:00:41 +02:00
Jeff a007f314e8 Merge pull request #95 from deavmi/master
Getting things ready for #primetime - Documentation Bulk Fixes 1
2016-06-05 08:00:10 -04:00
Tristan B. Kildaire 9728cf697b Update .gitignore 2016-06-05 13:59:18 +02:00
Tristan B. Kildaire 67cd4ab112 Update configure-postgres.md 2016-06-05 13:37:22 +02:00
Tristan B. Kildaire 435bfa17d5 Rename install-and-configure-postgres.md to configure-postgres.md 2016-06-05 13:32:04 +02:00
Tristan B. Kildaire b9373e44a1 Update setting-up.md 2016-06-05 13:31:46 +02:00
Tristan B. Kildaire 00153e3957 Rename install-and-configure-redis.md to configure-redis.md 2016-06-05 13:30:58 +02:00
Tristan B. Kildaire 588e19e93c Update install-and-configure-redis.md 2016-06-05 13:30:26 +02:00
Tristan B. Kildaire e9592b6021 Create Configuring Redis database 2016-06-05 13:30:24 +02:00
Tristan B. Kildaire 42ef4c4df1 Update install-and-configure-postgres.md 2016-06-05 13:29:43 +02:00
Tristan B. Kildaire dbb119bd8b Create Configuring Postgres database 2016-06-05 13:29:23 +02:00
Tristan B. Kildaire 9e3e597088 Update building.md 2016-06-05 13:28:44 +02:00
Tristan B. Kildaire e50099b7c0 Update building.md 2016-06-05 13:28:08 +02:00
Tristan B. Kildaire 55baec7af7 Update building.md 2016-06-05 13:27:16 +02:00
Tristan B. Kildaire 4ab24625fa Update building.md 2016-06-05 13:25:33 +02:00
Tristan B. Kildaire 1eed2cdd1a Update setting-up.md 2016-06-05 13:24:23 +02:00
Tristan B. Kildaire 43a81a6a4d Delete database.md 2016-06-05 13:22:23 +02:00
Tristan B. Kildaire 43dcbad33c Update README.md 2016-06-05 13:21:48 +02:00
Tristan B. Kildaire 89b51773eb Update building.md 2016-06-05 13:20:20 +02:00
Tristan B. Kildaire 47b722a825 Update building.md 2016-06-05 13:19:27 +02:00
Tristan B. Kildaire 76b6bad8a5 Update building.md 2016-06-05 13:18:58 +02:00
Tristan B. Kildaire 648b66cbbe Update building.md 2016-06-05 13:17:28 +02:00
Tristan B. Kildaire 1f2c644bf6 Update building.md 2016-06-05 13:16:22 +02:00
Tristan B. Kildaire 8aed629be6 Update building.md 2016-06-05 13:15:37 +02:00
Tristan B. Kildaire 9042f0f3b0 Update building.md 2016-06-05 13:13:14 +02:00
Tristan B. Kildaire a425ffea8f Update building.md 2016-06-05 13:11:16 +02:00
Tristan B. Kildaire a4a4eb7c2a Update srnd.go 2016-06-05 12:59:26 +02:00
Tristan B. Kildaire a01d5b0cee Update README.md 2016-06-05 12:13:10 +02:00
Tristan B. Kildaire 9f8ce5ab95 Update cli.md 2016-06-05 12:12:05 +02:00
Tristan B. Kildaire 880d1e10e3 Update running.md 2016-06-05 12:11:40 +02:00
Tristan B. Kildaire ff745ada70 Update running.md 2016-06-05 12:11:04 +02:00
Tristan B. Kildaire 68d7ec783d Update running.md 2016-06-05 12:08:52 +02:00
Tristan B. Kildaire a17f91fea1 Update README.md 2016-06-05 12:08:36 +02:00
Tristan B. Kildaire c5cf5ba4f9 Rename doc/configure-newsreader.md to doc/extras/configure-newsreader.md 2016-06-05 12:08:21 +02:00
Tristan B. Kildaire 9f9bebf99c Update setting-up.md 2016-06-05 12:07:22 +02:00
Tristan B. Kildaire 6ea1b2d3b4 Update setting-up.md 2016-06-05 12:06:25 +02:00
Tristan B. Kildaire acc727b901 Update setting-up.md 2016-06-05 12:05:21 +02:00
Tristan B. Kildaire 594cc4929a Update setting-up.md 2016-06-05 12:04:55 +02:00
Tristan B. Kildaire e0f15b73fb Rename doc/configuration-files.md to doc/.trash/configuration-files.md 2016-06-05 12:04:22 +02:00
Tristan B. Kildaire 0ac0d7d1ff Update building.md 2016-06-05 12:02:31 +02:00
Tristan B. Kildaire 9a6a4247ce Update README.md 2016-06-05 12:00:46 +02:00
Tristan B. Kildaire 22e384f2d1 Update install-and-configure-redis.md 2016-06-05 11:58:50 +02:00
Tristan B. Kildaire 7c668c5184 Update install-and-configure-postgres.md 2016-06-05 11:58:38 +02:00
Tristan B. Kildaire 91b6dbe9b2 Update setting-up.md 2016-06-05 11:58:12 +02:00
Tristan B. Kildaire 21566eb0d9 Update setting-up.md 2016-06-05 11:57:49 +02:00
Tristan B. Kildaire cc382572c6 Update setting-up.md 2016-06-05 11:57:37 +02:00
Tristan B. Kildaire 6e029cea0d Update README.md 2016-06-05 11:39:43 +02:00
Tristan B. Kildaire c92b78c754 Rename configuration.md to configuration-files.md 2016-06-05 11:38:25 +02:00
Tristan B. Kildaire 32eae178fb Update README.md 2016-06-05 11:37:55 +02:00
Tristan B. Kildaire 8a1936fade Update README.md 2016-06-05 11:37:33 +02:00
Tristan B. Kildaire edd44c73bf Update README.md 2016-06-05 11:36:30 +02:00
Tristan B. Kildaire b3d346c61f Update README.md 2016-06-05 11:36:12 +02:00
Tristan B. Kildaire ef124fe7f2 Update README.md 2016-06-05 11:36:04 +02:00
Tristan B. Kildaire 38f9db2f57 Update README.md 2016-06-05 11:35:42 +02:00
Tristan B. Kildaire e45c172e62 Update README.md 2016-06-05 11:35:34 +02:00
Tristan B. Kildaire 705f3b9df0 Update README.md 2016-06-05 11:35:14 +02:00
Tristan B. Kildaire 1f4e6c8ecb Update README.md 2016-06-05 11:34:54 +02:00
Tristan B. Kildaire 0831c250c4 Rename doc/trash/database.md to doc/.trash/database.md 2016-06-05 11:34:06 +02:00
Tristan B. Kildaire ecb462c0c3 Update README.md 2016-06-05 11:33:29 +02:00
Tristan B. Kildaire 6092f4e78e Update and rename doc/protocol.md to doc/developer/protocol.md 2016-06-05 11:33:08 +02:00
Tristan B. Kildaire 316729774a Update and rename doc/api.md to doc/developer/api.md 2016-06-05 11:33:06 +02:00
Tristan B. Kildaire c4f8fd118d Update install-and-configure-redis.md 2016-06-05 11:31:08 +02:00
Tristan B. Kildaire 543108e0d6 Update setting-up.md 2016-06-05 11:30:20 +02:00
Tristan B. Kildaire 6631b881b0 Rename doc/securing-redis.md to doc/database/redis/securing-redis.md 2016-06-05 11:30:00 +02:00
Tristan B. Kildaire 2d39c33f05 Rename doc/install-and-configure-postgres.md to doc/database/postgres/install-and-configure-postgres.md 2016-06-05 11:30:00 +02:00
Tristan B. Kildaire b32ff7b6ac Rename doc/install-and-configure-redis.md to doc/database/redis/install-and-configure-redis.md 2016-06-05 11:29:59 +02:00
Tristan B. Kildaire 9583b80ac5 Rename postgres.md to install-and-configure-postgres.md 2016-06-05 11:29:14 +02:00
Tristan B. Kildaire 71b46ef1f2 Update setting-up.md 2016-06-05 11:29:01 +02:00
Tristan B. Kildaire 5f0a353482 Rename redis.md to install-and-configure-redis.md 2016-06-05 11:28:37 +02:00
Tristan B. Kildaire 6eb84bf55e Update and rename doc/database.md to doc/trash/database.md 2016-06-05 11:28:08 +02:00
Tristan B. Kildaire e057ee1812 Update setting-up.md 2016-06-05 11:27:37 +02:00
Tristan B. Kildaire 279e9c18c9 Update setting-up.md 2016-06-05 11:26:57 +02:00
Tristan B. Kildaire 191dbc860c Update setting-up.md 2016-06-05 11:26:03 +02:00
Tristan B. Kildaire a9403410c8 Update feeds.md 2016-06-05 11:24:13 +02:00
Tristan B. Kildaire 6e2f245f24 Update configuration.md 2016-06-05 11:23:09 +02:00
Tristan B. Kildaire 6d20a991f8 Update redis.md 2016-06-05 11:20:25 +02:00
Tristan B. Kildaire d20de6b9b5 Update postgres.md 2016-06-05 11:20:06 +02:00
Tristan B. Kildaire fbb14cc719 Update redis.md 2016-06-05 11:19:53 +02:00
Tristan B. Kildaire 6bb1f4978e Update postgres.md 2016-06-05 11:19:52 +02:00
Tristan B. Kildaire 40d372efe3 Update postgres.md 2016-06-05 11:18:46 +02:00
Tristan B. Kildaire 51672e81c3 Update redis.md 2016-06-05 11:18:34 +02:00
Tristan B. Kildaire 5b06abe63d Update postgres.md 2016-06-05 11:17:58 +02:00
Tristan B. Kildaire 8ebe2d2d26 Update redis.md 2016-06-05 11:15:56 +02:00
Tristan B. Kildaire b020d13304 Update postgres.md 2016-06-05 11:15:51 +02:00
Tristan B. Kildaire aa9ae3d32f Update redis.md 2016-06-05 11:15:25 +02:00
Tristan B. Kildaire 53046ad1d2 Update postgres.md 2016-06-05 11:14:19 +02:00
Tristan B. Kildaire a851eddccf Update redis.md 2016-06-05 10:27:14 +02:00
Tristan B. Kildaire a2c33bc649 Update README.md 2016-06-05 10:24:31 +02:00
Tristan B. Kildaire e868b2c73b Update README.md 2016-06-05 10:13:04 +02:00
Tristan B. Kildaire 4de2b15959 Update srnd.md 2016-06-05 10:12:50 +02:00
Tristan B. Kildaire a57a3b283c Create configure-newsreader.md 2016-06-05 10:12:42 +02:00
Tristan B. Kildaire b9efd55a57 Update running.md 2016-06-05 10:12:22 +02:00
Tristan B. Kildaire 87097b7a06 Update README.md 2016-06-05 10:12:09 +02:00
Jeff c50aecc34d Merge pull request #88 from deavmi/patch-1
Update srnd.md
2016-06-04 15:27:06 -04:00
Tristan B. Kildaire 74e0d479a6 Update srnd.md 2016-06-04 21:26:19 +02:00
Tristan B. Kildaire 4420a65dfd Update srnd.md 2016-06-04 21:26:04 +02:00
Jeff b73ad00865 Merge pull request #87 from deavmi/patch-1
Update README.md
2016-06-04 15:25:41 -04:00
Tristan B. Kildaire 945e609dff Update README.md 2016-06-04 21:25:14 +02:00
Jeff 2c63c3d0ad Merge pull request #82 from deavmi/patch-4
Better name.
2016-06-04 15:12:48 -04:00
Jeff c86d58a44b Merge pull request #83 from deavmi/patch-5
Rename config.md to setting-up.md
2016-06-04 15:12:37 -04:00
Jeff 12ae47b9b6 Merge pull request #85 from deavmi/master
Some changes
2016-06-04 15:11:24 -04:00
Tristan B. Kildaire 27e19f3591 Update README.md 2016-06-04 21:10:17 +02:00
Tristan B. Kildaire 50a8ddd458 Update README.md 2016-06-04 21:09:13 +02:00
Tristan B. Kildaire 5690e80758 Update running.md 2016-06-04 21:08:58 +02:00
Tristan B. Kildaire 489b21fd04 Update README.md 2016-06-04 21:04:48 +02:00
Tristan B. Kildaire f9b08aa467 Rename build.md to building.md 2016-06-04 21:04:46 +02:00
Tristan B. Kildaire 85938d1f6b Merge pull request #1 from majestrate/master
f
2016-06-04 21:02:54 +02:00
Jeff a1d02708fa Merge pull request #80 from deavmi/patch-2
My eyes are bleeding from using GitHub's white-white editor
2016-06-04 15:01:59 -04:00
Tristan B. Kildaire f3f051fbf1 Rename config.md to setting-up.md 2016-06-04 21:00:59 +02:00
Jeff d078e58774 Merge pull request #81 from deavmi/patch-3
Looks better
2016-06-04 15:00:42 -04:00
Tristan B. Kildaire d8ecf670d5 Rename build.md to building.md 2016-06-04 20:59:39 +02:00
Tristan B. Kildaire 1bd84c839e Update srnd.md 2016-06-04 20:59:04 +02:00
Tristan B. Kildaire 5bfa14ba1a Update protocol.md 2016-06-04 20:57:52 +02:00
Jeff 7d258d9f3b Merge pull request #78 from deavmi/patch-2
Create README.md
2016-06-04 14:37:38 -04:00
Jeff 57d8fd4841 Merge pull request #77 from deavmi/patch-1
Update config.md
2016-06-04 14:37:33 -04:00
Tristan B. Kildaire a8653a472e Create README.md 2016-06-04 20:34:07 +02:00
Tristan B. Kildaire 45c0cf142d Update config.md 2016-06-04 20:32:26 +02:00
Jeff f53d9b8a5b Merge pull request #74 from deavmi/patch-2
Update README.md
2016-06-04 14:28:42 -04:00
Tristan B. Kildaire 42ea131dff Update README.md 2016-06-04 20:27:32 +02:00
Jeff 57ca993189 Merge pull request #71 from deavmi/patch-1
Work in progress afrikaans translations
2016-06-04 14:25:32 -04:00
Jeff 9d4b43c7e9 Merge pull request #73 from deavmi/patch-2
Create fr-FR.ini
2016-06-04 14:24:35 -04:00
Jeff 8802d5feef Merge pull request #70 from deavmi/master
add more documentation
2016-06-04 14:23:13 -04:00
Tristan B. Kildaire b8d58ab3e3 Update fr-FR.ini 2016-06-04 19:59:32 +02:00
Tristan B. Kildaire 00e2e4d03d Create fr-FR.ini 2016-06-04 19:57:13 +02:00
Tristan B. Kildaire 9ed02e4df0 Work in progress afrikaans translations 2016-06-04 19:54:03 +02:00
d 59a8e244a0 Nicer ending message. 2016-06-04 19:41:26 +02:00
d 3bd9e85682 : 2016-06-04 19:37:04 +02:00
Tristan B. Kildaire 3749445531 Update cli.md 2016-06-04 19:25:22 +02:00
Tristan B. Kildaire 5337fea89f Update cli.md 2016-06-04 19:25:06 +02:00
Tristan B. Kildaire 77e1f16624 Update cli.md 2016-06-04 19:24:12 +02:00
Tristan B. Kildaire 28b8c5059c Update securing-redis.md 2016-06-04 18:57:21 +02:00
Tristan B. Kildaire 285f5c271a Update config.md 2016-06-04 18:07:40 +02:00
Tristan B. Kildaire e143a78e20 Update config.md 2016-06-04 18:04:17 +02:00
Tristan B. Kildaire b9905ebae4 Update config.md 2016-06-04 18:01:40 +02:00
Tristan B. Kildaire 89dee3b72d Update config.md 2016-06-04 18:00:27 +02:00
Tristan B. Kildaire 18ea50ab18 Update config.md 2016-06-04 17:59:54 +02:00
Tristan B. Kildaire 1fb23dd34a Update config.md 2016-06-04 17:56:17 +02:00
Tristan B. Kildaire 6ce938b86a Update config.md 2016-06-04 17:55:50 +02:00
Tristan B. Kildaire a853409230 Update config.md 2016-06-04 17:55:01 +02:00
Tristan B. Kildaire cfeb11b545 Update config.md 2016-06-04 17:51:21 +02:00
Tristan B. Kildaire 963b893e39 Update config.md 2016-06-04 17:51:07 +02:00
Tristan B. Kildaire a75c22aecb Update config.md 2016-06-04 17:50:46 +02:00
Tristan B. Kildaire ca2d87e303 Update config.md 2016-06-04 17:50:02 +02:00
Tristan B. Kildaire bf143f07f7 Update config.md 2016-06-04 17:45:22 +02:00
Tristan B. Kildaire 850e61d923 Update config.md 2016-06-04 17:44:32 +02:00
Tristan B. Kildaire c5937bc3f7 Update config.md 2016-06-04 17:44:10 +02:00
Tristan B. Kildaire 4436c62fe2 Update config.md 2016-06-04 17:43:05 +02:00
Tristan B. Kildaire 71bb46cb5b Update README.md 2016-06-04 17:40:16 +02:00
Tristan B. Kildaire f06daf111a Update README.md 2016-06-04 17:40:09 +02:00
Tristan B. Kildaire 93434f3bf6 Update README.md 2016-06-04 17:39:34 +02:00
Tristan B. Kildaire 90aaad39bf Create config.md 2016-06-04 17:36:26 +02:00
Tristan B. Kildaire 8492cc35fa Update build.md 2016-06-04 17:35:00 +02:00
Tristan B. Kildaire 5087a0de7a Update build.md 2016-06-04 17:34:43 +02:00
Tristan B. Kildaire dfe6eae59f Update build.md 2016-06-04 17:32:57 +02:00
Tristan B. Kildaire 030a9e58e8 Update build.md 2016-06-04 17:31:24 +02:00
Tristan B. Kildaire 7a73cf3d55 Update build.md 2016-06-04 17:28:24 +02:00
Tristan B. Kildaire 8e1eb8620c Update build.md 2016-06-04 17:27:39 +02:00
Tristan B. Kildaire 546f4d413f Create securing-redis.md 2016-06-04 17:26:36 +02:00
Tristan B. Kildaire aa04d1d3ba Update build.md 2016-06-04 17:18:14 +02:00
Tristan B. Kildaire 27eae6750c Update build.md 2016-06-04 17:18:03 +02:00
Tristan B. Kildaire 3174aaad22 Update build.md 2016-06-04 17:17:54 +02:00
Tristan B. Kildaire 89c4fe4a96 Update build.md 2016-06-04 17:16:55 +02:00
Tristan B. Kildaire 4f204fd873 Update build.md 2016-06-04 17:16:08 +02:00
Tristan B. Kildaire 7612b629ad Update README.md 2016-06-04 17:11:06 +02:00
Tristan B. Kildaire 0d5b0ddb0b Update README.md 2016-06-04 17:09:35 +02:00
Tristan B. Kildaire b41d2fa532 Update README.md 2016-06-04 17:08:46 +02:00
Tristan B. Kildaire 52239bebc3 Update README.md 2016-06-04 17:08:25 +02:00
Jeff a7a97709fe Merge pull request #68 from ZiRo-/master
add filenames to images
2016-05-22 17:54:26 -04:00
ZiRo e0789c8f90 add filenames to images 2016-05-22 22:51:26 +02:00
Jeff c5e90ec550 Merge pull request #67 from ZiRo-/master
add download link for files with original filename
2016-05-22 15:17:19 -04:00
ZiRo 6840c28cb8 Merge remote-tracking branch 'upstream/master' 2016-05-22 20:22:31 +02:00
ZiRo 41caf046a0 add download link for files 2016-05-22 20:22:12 +02:00
Jeff deb5a36c0d Merge pull request #66 from ZiRo-/master
add captcha reload script
2016-05-22 06:03:09 -04:00
ZiRo 920ddb64b3 add captcha reload script 2016-05-22 07:51:12 +02:00
Jeff Becker af59a38a40 Revert "fix prefixing for overview template"
This reverts commit 8401c5a25d.
2016-05-20 06:25:30 -04:00
Jeff 8bca301e55 Merge pull request #63 from ZiRo-/master
fix prefixing for overview template
2016-05-20 06:12:59 -04:00
ZiRo 8401c5a25d fix prefixing for overview template 2016-05-20 07:03:54 +02:00
Jeff ab44cb2457 * add generated javascript files to .gitignore
* untrack generated javascript files

* regen generated javascript via build.sh by default
2016-05-18 13:22:56 -04:00
Jeff e831a56809 move cuckoo-miner building to build-js.sh 2016-05-18 13:16:06 -04:00
Jeff 84cac4ceec Merge pull request #62 from ZiRo-/master
make miner multi threaded
2016-05-18 12:59:07 -04:00
ZiRo e372893373 make miner multi threaded 2016-05-18 18:54:05 +02:00
Jeff 4f0ae8fec3 Merge pull request #61 from ZiRo-/master
make final adjustments to the siphash function
2016-05-18 10:22:24 -04:00
ZiRo 7f445f81fc make final adjustments to the siphash function 2016-05-18 16:17:41 +02:00
Jeff 28c18afaf9 Merge pull request #60 from ZiRo-/master
use native js function for siphash
2016-05-18 07:59:46 -04:00
ZiRo 6008c94949 use native js function for siphash 2016-05-18 13:41:20 +02:00
Jeff 8dc1218934 Merge pull request #59 from ZiRo-/master
make postform more compact
2016-05-17 17:57:19 -04:00
ZiRo 11204cba16 make postform more compact 2016-05-17 16:33:14 +02:00
Jeff e3928bc6c2 Merge pull request #58 from ZiRo-/master
add cuckoo miner to postform
2016-05-17 07:52:44 -04:00
ZiRo c2bd325be6 add miner.js to build.sh 2016-05-17 13:27:29 +02:00
ZiRo 941c4a3a9f indicate mining process 2016-05-17 08:55:21 +02:00
ZiRo 261493af0b add cuckoo miner to postform 2016-05-17 08:24:46 +02:00
Jeff Becker 1791fc475b bump ipfs version 2016-05-15 08:19:03 -04:00
Jeff Becker de7cec2c43 try another way using build.sh 2016-05-13 10:50:18 -04:00
Jeff Becker e7c90c647d ammend build.sh to use mv not cp with finished binary 2016-05-13 10:47:56 -04:00
Jeff Becker 9596c1e27e try simpler build.sh 2016-05-13 10:41:51 -04:00
Jeff Becker c86732ba5c try fixing build.sh 2016-05-13 10:36:56 -04:00
Jeff Becker 2a7c15241f add meaningful message before long pause of gx 2016-05-13 10:29:46 -04:00
Jeff Becker d2d81ccbd0 try to make build.sh work 2016-05-13 10:16:09 -04:00
Jeff Becker 78a5138409 try using -d flag 2016-05-13 10:14:27 -04:00
Jeff Becker bdd9ae9ae4 try again 2016-05-13 10:12:58 -04:00
Jeff Becker a8a98b03fb ugh 2016-05-13 10:12:11 -04:00
Jeff Becker 4a5fd4aba0 try fixing borked build.sh 2016-05-13 10:11:28 -04:00
Jeff Becker 2de7c633d4 tweak build.sh 2016-05-13 10:10:12 -04:00
Jeff Becker 56c72d1d74 use go get instead of go build 2016-05-13 10:06:39 -04:00
Jeff Becker f3793852a2 try fixing build.sh again 2016-05-13 10:05:49 -04:00
Jeff Becker 382875509b try correcting location of vendor packages 2016-05-13 10:04:04 -04:00
Jeff Becker 5da696d1c8 fix checks for gx and gx-go 2016-05-13 09:56:51 -04:00
Jeff Becker 7f1800a0c6 only obtain gx if we do not have it 2016-05-13 09:52:35 -04:00
Jeff Becker 504c9ae84e fix missing command 2016-05-13 09:51:35 -04:00
Jeff Becker 63a3511c84 remove redundant command 2016-05-13 09:49:48 -04:00
Jeff Becker 309d8e6c45 tweak build.sh 2016-05-13 09:47:01 -04:00
Jeff Becker 403c404ced tweak build.sh 2016-05-13 09:44:14 -04:00
Jeff Becker 133b032f1d tweak build.sh again 2016-05-13 09:38:57 -04:00
Jeff Becker ac0b171f19 tweak build.sh 2016-05-13 09:37:32 -04:00
Jeff Becker 0e57fe057f update build.sh to use vendor 2016-05-13 09:33:59 -04:00
Jeff Becker 6e4398f0c2 update gx stuffs 2016-05-13 09:30:24 -04:00
Jeff Becker 136a0878af remove mp3 from repo so gx publish doesn't take forever 2016-05-13 09:01:08 -04:00
Jeff Becker 813c00e3ea bump package version 2016-05-13 08:57:29 -04:00
Jeff Becker d8625a1cb5 update ipfs hashes 2016-05-13 08:49:43 -04:00
Jeff c7d322c09d fix :^) 2016-05-08 08:36:42 -04:00
Jeff f7e8359f7b fix typo 2016-05-04 14:03:48 -04:00
Jeff 3283e53c5c show reply box on ukko page 2016-05-04 14:02:04 -04:00
Jeff fb2b80335e don't show reply box if not created 2016-05-04 13:14:57 -04:00
Jeff 96f6044489 try to make sure e is not null 2016-05-04 13:12:46 -04:00
Jeff 8f1a497f13 update minified 2016-05-04 13:10:55 -04:00
Jeff 272fe26b26 style changes 2016-05-04 13:10:46 -04:00
Jeff dec1a3e78d add debugging 2016-05-04 13:06:15 -04:00
Jeff 85ce14091a disable replybox on thread and board pages, default to overchan.random for livechand ukko pages 2016-05-04 13:03:32 -04:00
Jeff faf5071740 add comment 2016-05-03 15:20:08 -04:00
Jeff aadf8a9bfa remove conflicting css 2016-05-03 15:14:00 -04:00
Jeff 6ccb829fb9 remove unneeded functions 2016-05-03 15:12:11 -04:00
Jeff 3be1c3e081 try fixing style 2016-05-03 15:10:26 -04:00
Jeff 3e20e100f5 fug 2016-05-03 15:08:16 -04:00
Jeff f227786e33 try fixing drag to move behavior 2016-05-03 15:07:20 -04:00
Jeff 82d71588e9 try fixing undefined behavior 2016-05-03 15:06:00 -04:00
Jeff 521c135498 use stack overflow example 2016-05-03 15:04:38 -04:00
Jeff ae45d3e516 try fixing drag and drop 2016-05-03 15:02:01 -04:00
Jeff 363bf49799 try fixing undefined behavior on drag 2016-05-03 15:00:58 -04:00
Jeff 8782dffeae fix typo 2016-05-03 15:00:11 -04:00
Jeff da4e56fe25 add jquery :< 2016-05-03 14:58:57 -04:00
Jeff eb9a8e5174 try fix 2016-05-03 14:43:42 -04:00
Jeff bd45322509 try fix 2016-05-03 14:43:23 -04:00
Jeff 2705a111c6 try fix 2016-05-03 14:42:53 -04:00
Jeff bb748f9a74 try fix 2016-05-03 14:41:51 -04:00
Jeff 1ef0430392 try fix 2016-05-03 14:39:17 -04:00
Jeff 2415c10029 try fix 2016-05-03 14:37:23 -04:00
Jeff f6f84f25c8 try fix 2016-05-03 14:36:18 -04:00
Jeff 23c4f455d5 try fix 2016-05-03 14:34:40 -04:00
Jeff b1ebd3826a try fix 2016-05-03 14:33:41 -04:00
Jeff 914c69215e try fix 2016-05-03 14:30:21 -04:00
Jeff fdb34a7816 try fix 2016-05-03 14:30:06 -04:00
Jeff 21b80ecc8d try fix 2016-05-03 14:29:23 -04:00
Jeff d0d1bed10a try fix 2016-05-03 14:27:07 -04:00
Jeff 2613c57bf8 try fix 2016-05-03 14:25:32 -04:00
Jeff 43bb6e4c5c try fix 2016-05-03 14:23:45 -04:00
Jeff 7136b176ee try fix 2016-05-03 14:22:10 -04:00
Jeff 7767b6d436 try fix 2016-05-03 14:20:35 -04:00
Jeff 98b2834bd1 try fix 2016-05-03 14:19:16 -04:00
Jeff d1f540f99a try fix 2016-05-03 14:17:41 -04:00
Jeff 7bdb104fcf try fix 2016-05-03 14:16:15 -04:00
Jeff 9e68e626c9 try fix 2016-05-03 14:13:48 -04:00
Jeff 7df2e6c83b try fix 2016-05-03 14:09:47 -04:00
Jeff 9aca55ec71 try fix 2016-05-03 14:08:58 -04:00
Jeff 9f55486107 try fix 2016-05-03 14:07:48 -04:00
Jeff 4e161a5d70 try fix 2016-05-03 14:06:22 -04:00
Jeff ee3b067555 try fix 2016-05-03 14:05:27 -04:00
Jeff 64c5b1589b try fix 2016-05-03 14:03:19 -04:00
Jeff 7b3a6329a6 try fix 2016-05-03 14:02:13 -04:00
Jeff fab83592b7 try fix 2016-05-03 13:59:10 -04:00
Jeff 7b8d229b64 try fix 2016-05-03 13:57:48 -04:00
Jeff b2d0bfea8c try fix 2016-05-03 13:57:01 -04:00
Jeff 9ce09c34c3 try fix 2016-05-03 13:55:22 -04:00
Jeff fdd9bab210 try fix 2016-05-03 13:47:28 -04:00
Jeff ee73b907de try fix 2016-05-03 13:46:32 -04:00
Jeff 27192b0248 try fix 2016-05-03 13:24:49 -04:00
Jeff 45267caa0a try fix 2016-05-03 13:16:36 -04:00
Jeff f6576aa899 try fix 2016-05-03 13:16:18 -04:00
Jeff ce8180c804 try fix 2016-05-03 13:15:20 -04:00
Jeff 5375252783 try fix 2016-05-03 13:14:39 -04:00
Jeff cc5806a035 try fix 2016-05-03 13:13:54 -04:00
Jeff 1fa694282b try fix 2016-05-03 13:09:05 -04:00
Jeff f94491e38d try fix 2016-05-03 13:08:07 -04:00
Jeff df4b263f39 try fix 2016-05-03 13:05:45 -04:00
Jeff 3fb94baaca revert to clientX/Y 2016-05-03 13:01:55 -04:00
Jeff be7831cd10 use shift key for drag 2016-05-03 13:00:41 -04:00
Jeff 7daa0f8520 use screenX/y instead of clientX/y 2016-05-03 12:38:46 -04:00
Jeff 7afd47805a remove stray assignment 2016-05-03 12:35:46 -04:00
Jeff def0a4a5c5 adgo back to drag events 2016-05-03 12:33:24 -04:00
Jeff 3fdda45425 add debugging and try new method for drag 2016-05-03 12:30:59 -04:00
Jeff 56a345949d try using different drag method for reply box 2016-05-03 12:28:19 -04:00
Jeff 2a08f73db4 use alternative layout in postform for postform_msg 2016-05-03 12:17:08 -04:00
Jeff 52bafb364d update build scripts to work with non-gnu readlink 2016-05-03 12:16:36 -04:00
Jeff a4c70fe77b rename backlink.js to reply.js 2016-05-03 11:44:08 -04:00
Jeff Becker 58d32b5d1d don't double post 2016-05-01 18:04:43 -04:00
Jeff Becker a389c8b82d make image expansion case insensitive 2016-05-01 17:56:47 -04:00
Jeff Becker c8e8ab95cd "" -> null aka, js is shit 2016-05-01 17:48:17 -04:00
Jeff Becker 331fed1731 try blanking out attachments after posting 2016-05-01 17:38:37 -04:00
Jeff Becker 5bcbe255b1 change post success message 2016-05-01 17:27:08 -04:00
Jeff Becker ba045b6903 show "posting..." message right before posting 2016-05-01 17:25:08 -04:00
Jeff Becker 187eef590d try clearing reply box on success 2016-05-01 10:42:06 -04:00
Jeff Becker 06ff6554d4 return false for onsubmit 2016-05-01 10:34:05 -04:00
Jeff Becker d217776201 try using onsubmit for reply box form 2016-05-01 10:31:14 -04:00
Jeff Becker 76949151de fix typo 2016-04-30 16:36:21 -04:00
Jeff Becker a6f418d3a9 try using ctl drag 2016-04-30 16:32:10 -04:00
Jeff Becker fa27cc64ef fug 2016-04-30 16:29:41 -04:00
Jeff Becker e042d0fef7 use shift+drag for moving reply box 2016-04-30 16:28:26 -04:00
Jeff Becker 2eefe2e301 use alt+click drag for moving reply box 2016-04-30 16:25:27 -04:00
Jeff Becker b1c1e4fab3 use prevent default in drag 2016-04-30 16:23:13 -04:00
Jeff Becker 68a83205ab add captcha updating 2016-04-30 16:20:27 -04:00
Jeff Becker 950441ef45 fix variable name 2016-04-30 16:19:08 -04:00
Jeff Becker e01002ed25 fix posting style 2016-04-30 16:18:08 -04:00
Jeff Becker 9d7eceb927 use appendChild 2016-04-30 16:14:47 -04:00
Jeff Becker 2b28431568 add posting message 2016-04-30 16:12:01 -04:00
Jeff Becker 0df3fe43e0 fix undefined error 2016-04-30 16:11:20 -04:00
Jeff Becker 1a3fe3af66 try fixing bug where reply box exists but doesn't submit 2016-04-30 16:09:59 -04:00
Jeff Becker 6d6ba47b2c try fixing async posting 2016-04-30 16:08:11 -04:00
Jeff Becker d47d390536 try implementing async post via reply box 2016-04-30 16:03:39 -04:00
Jeff Becker 157d1f8cb9 be aware of screen size 2016-04-30 15:13:52 -04:00
Jeff Becker 5df2ecac0c debug fixes 2016-04-30 15:11:32 -04:00
Jeff Becker 1452be84bf fug 2016-04-30 15:10:15 -04:00
Jeff Becker d5d005e74b try fix again 2016-04-30 15:09:01 -04:00
Jeff Becker 846fe26ec5 try aligning right 2016-04-30 15:07:56 -04:00
Jeff Becker 940ac4dec0 fuggg 2016-04-30 15:07:07 -04:00
Jeff Becker 3a26c3e38e try to fix movement of reply box 2016-04-30 15:06:12 -04:00
Jeff Becker 0a4a3b4f8a screenX -> screenLeft 2016-04-30 15:05:31 -04:00
Jeff Becker 11f096e195 try fixing movement of reply box 2016-04-30 15:04:53 -04:00
Jeff Becker 02330805e9 try fixing movement of reply window 2016-04-30 15:03:54 -04:00
Jeff Becker ed5be31c22 try fixing movement 2016-04-30 15:02:09 -04:00
Jeff Becker d99a222434 add semicolon 2016-04-30 15:01:11 -04:00
Jeff Becker 01bd911084 try fixing oob 2016-04-30 15:00:34 -04:00
Jeff Becker 79ae266424 different initial position 2016-04-30 14:57:57 -04:00
Jeff Becker e9db85c5b6 add semi-colins, this aint go 2016-04-30 14:57:07 -04:00
Jeff Becker d82f2e3732 use different method for moveto 2016-04-30 14:56:22 -04:00
Jeff Becker 2d9aac039c enable dragable 2016-04-30 14:54:24 -04:00
Jeff Becker 917b15156c ugh 2016-04-30 14:53:32 -04:00
Jeff Becker b03b18b05f fix? 2016-04-30 14:52:56 -04:00
Jeff Becker 7527e4c978 try fixing drag to move again 2016-04-30 14:52:19 -04:00
Jeff Becker 702dcf7997 try making not dragable 2016-04-30 14:49:09 -04:00
Jeff Becker 5cd2c3d43a more fixes in drag to move 2016-04-30 14:48:30 -04:00
Jeff Becker 3e4d128b9c fix 2016-04-30 14:46:05 -04:00
Jeff Becker ecb223ebc4 try fixing drag to move for reply box 2016-04-30 14:44:06 -04:00
Jeff Becker 61e390daf0 add logging 2016-04-30 13:32:38 -04:00
Jeff Becker 4264004eaf fix x,y 2016-04-30 13:31:57 -04:00
Jeff Becker ac4eb96a69 add px to style 2016-04-30 13:31:03 -04:00
Jeff Becker d59cb4f9a8 again 2016-04-30 13:28:59 -04:00
Jeff Becker ad1ff687f6 try fixing drag to move 2016-04-30 13:27:54 -04:00
Jeff Becker 480c40ce4f try fixing drag to move 2016-04-30 13:26:42 -04:00
Jeff Becker a1142aa670 again 2016-04-30 13:25:29 -04:00
Jeff Becker 6fddac0245 try fixing drag to move 2016-04-30 13:24:13 -04:00
Jeff Becker 531da63e7b try fixing drag to move 2016-04-30 13:22:17 -04:00
Jeff Becker d52a63586f update drag to move for post form 2016-04-30 13:19:34 -04:00
Jeff Becker 3710ed884e start adding move by drag to reply box 2016-04-30 13:18:17 -04:00
Jeff Becker 9019bf2e9a update reply box css 2016-04-30 13:10:04 -04:00
Jeff Becker de6d2964f9 update reply box 2016-04-30 13:09:40 -04:00
Jeff Becker 12f5e67bb4 css update 2016-04-30 13:08:38 -04:00
Jeff Becker b71d62ca35 fix quickreply 2016-04-30 13:06:29 -04:00
Jeff Becker fffe030fa2 update dynamic reply 2016-04-30 13:03:18 -04:00
Jeff Becker 74099cb5f2 css fix 2016-04-30 13:01:36 -04:00
Jeff Becker d55716dc9b update css and position for reply box 2016-04-30 13:00:27 -04:00
Jeff Becker dabbf4d143 update position of post reply box 2016-04-30 12:58:24 -04:00
Jeff Becker 048300d6e4 fix js id for postform_container 2016-04-30 12:56:24 -04:00
Jeff Becker 3a1a24f6da fix css 2016-04-30 12:55:43 -04:00
Jeff Becker 5fccdeba45 fix css typo 2016-04-30 12:53:01 -04:00
Jeff Becker 72e10a8734 update css 2016-04-30 12:52:16 -04:00
Jeff Becker b78054a751 update css 2016-04-30 12:51:20 -04:00
Jeff Becker c394114c4e update class for dynamic postform 2016-04-30 12:42:30 -04:00
Jeff Becker 7aa6eb28b2 append table row 2016-04-30 12:41:23 -04:00
Jeff Becker a96b4d0585 document.appendChild -> document.body.appendChild 2016-04-30 12:39:46 -04:00
Jeff Becker c8217dad84 try fixing dynamic reply 2016-04-30 12:37:36 -04:00
Jeff Becker 926aa0b69f try fixing dynamic reply 2016-04-30 12:35:21 -04:00
Jeff Becker a51f9a77e6 more debugging 2016-04-30 12:34:29 -04:00
Jeff Becker f0fd23e6a9 more logging 2016-04-30 12:33:29 -04:00
Jeff Becker 85dc5da83a add logging 2016-04-30 12:29:51 -04:00
Jeff Becker 1b7526ff2f initial dynamic reply code 2016-04-30 12:25:15 -04:00
Jeff Becker 982cbf2eb1 update minified 2016-04-30 10:08:44 -04:00
Jeff Becker c455edcd59 don't include mathjax in minified js 2016-04-30 10:05:06 -04:00
Jeff Becker ed489f9d89 use correct git command 2016-04-30 09:59:59 -04:00
Jeff Becker 07d6bc2cd7 update build-js.sh to check for submodule correctly 2016-04-30 09:59:17 -04:00
Jeff Becker cdcd0ce68d add mathjax submodule 2016-04-30 09:58:21 -04:00
Jeff Becker 861acbbe0a revert css to not use flex 2016-04-30 09:11:33 -04:00
Jeff Becker 7e47470cea fix bug with inline image expand where br element leaves spaces after expand 2016-04-30 09:06:08 -04:00
Jeff Becker d1bf4cc7f3 update css 2016-04-30 09:02:50 -04:00
Jeff Becker e2968dbd97 fix js 2016-04-30 08:51:49 -04:00
Jeff Becker ed62c4e879 update image-inline 2016-04-30 08:51:01 -04:00
Jeff Becker a02c6f040e update css 2016-04-30 08:48:28 -04:00
Jeff Becker 7022dbf8c1 try fixing inline expand again 2016-04-30 08:42:54 -04:00
Jeff Becker 14cf2cbe5b again 2016-04-30 08:40:21 -04:00
Jeff Becker 6a73f5d727 try again 2016-04-30 08:38:50 -04:00
Jeff Becker 5a069dbb9a try fixing inline image more 2016-04-30 08:38:11 -04:00
Jeff Becker 77be791ce7 try fixing inline image expand again 2016-04-30 08:36:46 -04:00
Jeff Becker d69ee3a8d0 try fixing image-inline 2016-04-30 08:34:33 -04:00
Jeff Becker 115e2884c1 fix url for image inline 2016-04-30 08:32:28 -04:00
Jeff Becker f9ab15e271 add debugging 2016-04-30 08:31:37 -04:00
Jeff Becker 6c5aed6a3c bugfix 2016-04-30 08:30:14 -04:00
Jeff Becker cc0a0bc269 add initial expand images js 2016-04-30 08:26:14 -04:00
Jeff Becker fe2fb50775 add doctype 2016-04-29 14:08:02 -04:00
Jeff a423b6bfe6 Merge pull request #56 from ZiRo-/master
Add inline webm playback & make js files modular
2016-04-27 13:47:36 +00:00
ZiRo 7441463de3 copy&past is bad 2016-04-27 15:40:41 +02:00
ZiRo 2dea0917d1 Add inline webm playback 2016-04-27 15:36:57 +02:00
ZiRo d059971dcc make js more modular 2016-04-27 14:21:12 +02:00
Jeff Becker fd60d92728 css tweak, use :target 2016-04-26 09:43:11 -04:00
Jeff Becker 4737932a3e css tweak 2016-04-26 09:40:06 -04:00
Jeff Becker 32c5df4ffd css fix for hover 2016-04-26 09:36:02 -04:00
Jeff Becker dede4299dc fix hover a bit 2016-04-26 09:23:38 -04:00
Jeff Becker 57afa2ce4b backlinks sorta work 2016-04-26 09:13:04 -04:00
Jeff Becker 4a79b1c998 tweak scrollback limit and add "readonly" note 2016-04-25 17:17:59 -04:00
Jeff Becker 5443e06b38 reconnect liveui on close 2016-04-25 17:08:31 -04:00
Jeff Becker 69f08dbb58 fixups 2016-04-25 16:47:14 -04:00
Jeff Becker 9f5409a66a fix live.mustache 2016-04-25 16:33:51 -04:00
Jeff Becker 6ff21ebaeb insert placeholder so livechan widget calls onload 2016-04-25 16:32:10 -04:00
Jeff Becker 14fe9fe916 add liveui page 2016-04-25 16:29:11 -04:00
Jeff Becker 5c66f4684a liveui 2016-04-25 15:57:49 -04:00
Jeff Becker 6797e68ddd up error screen waiting time 2016-04-22 17:59:44 -04:00
Jeff Becker 86088b52e8 up wait time on post success page 2016-04-21 21:27:00 -04:00
Jeff Becker b44c711483 try fixing catalog theme changer 2016-04-21 15:44:34 -04:00
Jeff Becker d38ff65c22 use old style build D: 2016-04-18 19:42:24 -04:00
Jeff Becker 02cafc2cc5 update to next hash 2016-04-18 17:11:40 -04:00
Jeff Becker d956f5334c ignore nntpchan bin in gitignore 2016-04-18 09:58:28 -04:00
Jeff Becker 3799c8caa1 try fixing build.sh more again again 2016-04-18 09:33:40 -04:00
Jeff Becker bcb12ecb0f try fixing build.sh AGAIN 2016-04-18 09:27:53 -04:00
Jeff Becker b89ca0dc72 try fixing build.sh again 2016-04-18 09:26:09 -04:00
Jeff Becker 893491ce25 try fixing build.sh 2016-04-18 09:22:33 -04:00
Jeff Becker 51d031566a fix build.sh more 2016-04-18 08:47:48 -04:00
Jeff Becker a54b928a67 fix build.sh 2016-04-18 08:46:46 -04:00
Jeff Becker 8ac1c210f2 use gx for package management 2016-04-18 08:40:01 -04:00
Jeff Becker 8d83e4dbaf update readme 2016-04-18 08:09:42 -04:00
Jeff Becker d4a200e921 update readme to include both githug and gitgud links for bugs 2016-04-18 08:08:06 -04:00
Jeff Becker e1f9efffbc update readme to include frontend list 2016-04-17 17:52:12 -04:00
Jeff Becker 61de708062 add tomorrow css theme from TJBK 2016-04-15 20:17:32 -04:00
Jeff Becker 411230f48a fix 2016-04-12 19:41:38 -04:00
Jeff Becker 5530ae113e fix 2016-04-12 19:40:55 -04:00
Jeff Becker 29b2db8198 update csrf 2016-04-12 19:39:56 -04:00
Jeff Becker bc239360ea update docs to include info about web ui installer 2016-04-03 08:57:02 -04:00
Jeff Becker 558553a587 Merge branch 'master' of ssh://github.com/majestrate/nntpchan 2016-04-03 08:17:55 -04:00
Jeff Becker 23752f0996 update docs 2016-04-03 08:17:36 -04:00
Jeff 317bbbf457 Merge pull request #54 from ZiRo-/master
Add installer
2016-03-29 17:47:10 +00:00
ZiRo 177082fded Even more installer dialogs 2016-03-29 18:48:37 +02:00
ZiRo 323f2f150c Some more installer dialogs 2016-03-29 15:58:28 +02:00
ZiRo 44ff1d2fb6 Add database installer 2016-03-29 13:38:38 +02:00
ZiRo 390574ed45 initial installer 2016-03-28 15:34:38 +02:00
Jeff Becker 60dec3db4a fix typo 2016-03-25 10:06:56 -04:00
Jeff Becker 00a69ad685 add sync all feeds part to feeds page 2016-03-25 10:03:31 -04:00
Jeff Becker 2959be4564 another check for no element 2016-03-25 10:01:33 -04:00
Jeff Becker 5d14475373 add link to nntp feed page on mod panel 2016-03-25 10:00:21 -04:00
Jeff Becker 62e59d4201 add check for mod feed page, feeds page does not have nntpchan_mod_target element 2016-03-25 09:57:38 -04:00
Jeff Becker af02424d20 move call of initial update function to script block 2016-03-25 09:53:47 -04:00
Jeff Becker 33c6c33af2 update mod panel, begin migration to gx 2016-03-25 09:48:19 -04:00
Jeff Becker 7a67e38bf1 add .gxignore 2016-03-23 09:45:06 -04:00
1551 changed files with 580546 additions and 706 deletions
+10 -1
View File
@@ -19,7 +19,7 @@ webroot
# built binaries
go
srndv2
./srndv2
# private key
*.key
@@ -29,3 +29,12 @@ certs
rebuild.sh
.gx
# generated js
contrib/static/nntpchan.js
contrib/static/js/nntpchan.js
contrib/static/miner-js.js
#docs trash
doc/.trash
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015 Jeff Becker
Copyright (c) 2015-2017 Jeff Becker
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+41
View File
@@ -0,0 +1,41 @@
REPO=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
REPO_GOPATH=$(REPO)/go
MINIFY=$(REPO_GOPATH)/bin/minify
JS=$(REPO)/contrib/static/nntpchan.js
CONTRIB_JS=$(REPO)/contrib/js/contrib
LOCAL_JS=$(REPO)/contrib/js/nntpchan
VENDOR_JS=$(REPO)/contrib/js/vendor
SRND_DIR=$(REPO)/contrib/backends/srndv2
SRND=$(REPO)/srndv2
all: clean build
build: js srnd
js: $(JS)
srnd: $(SRND)
$(MINIFY):
GOPATH=$(REPO_GOPATH) go get -v github.com/tdewolff/minify/cmd/minify
js-deps: $(MINIFY)
$(JS): js-deps
rm -f $(JS)
for f in $(CONTRIB_JS)/*.js ; do $(MINIFY) --mime=text/javascript >> $(JS) < $$f ; done
$(MINIFY) --mime=text/javascript >> $(JS) < $(REPO)/contrib/js/entry.js
for f in $(LOCAL_JS)/*.js ; do $(MINIFY) --mime=text/javascript >> $(JS) < $$f ; done
for f in $(VENDOR_JS)/*.js ; do $(MINIFY) --mime=text/javascript >> $(JS) < $$f ; done
$(SRND):
$(MAKE) -C $(SRND_DIR)
cp $(SRND_DIR)/srndv2 $(SRND)
clean:
rm -f $(SRND) $(JS)
$(MAKE) -C $(SRND_DIR) clean
distclean: clean
rm -rf $(REPO_GOPATH)
+40 -12
View File
@@ -1,26 +1,54 @@
# NNTPChan #
[NNTPChan](https://nntpchan.info)
=================================
NNTPChan (previously known as overchan) is a decentralized imageboard that uses nntp to synchronize content between many different servers. It utilizes cryptographically signed posts to perform optional/opt-in decentralized moderation.
![le ebin logo](nntpchan.png "ebin logo")
This repository contains resources used by the core daemon which is located [here](https://github.com/majestrate/srndv2) along with general documentation, [here](doc/)
**NNTPChan** (previously known as overchan) is a decentralized imageboard that uses the [NNTP protocol](https://en.wikipedia.org/wiki/Network_News_Transfer_Protocol) (network-news transfer protocol) to synchronize content between many different servers. It utilizes cryptographically signed posts to perform optional/opt-in decentralized moderation.
## getting started ##
## Getting started
[This](doc) is a step-by-step guide for getting up-and-running with NNTPChan as well as documentation for developers who want to either work on NNTPChan directly or use NNTPChan in their aplications with the API.
## Bugs and issues
*PLEASE* report any bugs you find while building, setting-up or using NNTPChan on the [GitHub issue tracker](https://github.com/majestrate/nntpchan/issues), the [issue tracker on tor](http://git.psii2pdloxelodts.onion/psi/nntpchan/), the [issue tracker on i2p](http://git.psi.i2p/psi/nntpchan/) or on the [GitGud issue tracker](https://gitgud.io/jeff/nntpchan/issues) so that the probelms can be resolved or discussed.
## Clients
NNTP (confirmed working):
* Thunderbird
Web:
* [Yukko](https://github.com/faissaloo/Yukko): ncurses based nntpchan web ui reader
[see build documentation](doc/build.md)
## Support
---
Need help? Join us on IRC.
*PLEASE* report any bugs you find while setting up or building [(here)](https://github.com/majestrate/nntpchan/issues) so that the problems get fixed :^)
1. [freenode: #nntpchan](https://webchat.freenode.net/?channels=#nntpchan)
2. [rizon: #nntpchan](https://qchat.rizon.net/?channels=#nntpchan) - Most active
IRC:
## History
[freenode: #nntpchan](https://webchat.freenode.net/?channels=#nntpchan)
* started in mid 2013 on anonet
[rizon: #nntpchan](https://qchat.rizon.net/?channels=#nntpchan)
This is a graph of the post flow of the `overchan.test` newsgroup over 4 years, quite a big network.
(thnx anon who made this btw)
Like this project? Fund it:
![network topology of 4 years](topology.png "changolia")
bitcoin: 15yuMzuueV8y5vPQQ39ZqQVz5Ey98DNrjE
## Donations
Like this project? Why not help by funding it? This address pays for the server that runs `2hu-ch.org`
Bitcoin: [15yuMzuueV8y5vPQQ39ZqQVz5Ey98DNrjE](bitcoin://15yuMzuueV8y5vPQQ39ZqQVz5Ey98DNrjE)
Monero: 46thSVXSPNhJkCgUsFD9WuCjW4K41DAHGL9khni2VEqmZZhfEZVvcukCp357rfhngZdviZMaeNdj5CLqhLyeK2qZRBCyL7Q
## Acknowledgements
* [Deavmi](https://deavmi.carteronline.net/) - Making the documentation beautiful.
+3 -2
View File
@@ -1,6 +1,7 @@
## TODO ##
* extra stylesheets
* more alternative templates
* javascript free mod panel
* liveui
* better mod panel
* easier peering
* improve command line mod tools
-33
View File
@@ -1,33 +0,0 @@
#!/usr/bin/env bash
set -e
root=$(readlink -e $(dirname $0))
tags=""
help_text="usage: $0 [--disable-redis]"
# check for help flags first
for arg in $@ ; do
case $arg in
-h|--help)
echo $help_text
exit 0
;;
esac
done
# check for build flags
for arg in $@ ; do
case $arg in
"--disable-redis")
tags="$tags -tags disable_redis"
;;
esac
done
cd $root
export GOPATH=$root/go
mkdir -p $GOPATH
go get -v -u $tags github.com/majestrate/srndv2
cp -a $GOPATH/bin/srndv2 $root
echo "Built"
@@ -0,0 +1,6 @@
*.o
*.a
nntpd
tools/authtool
tools/testtool
.gdb_history
+54
View File
@@ -0,0 +1,54 @@
REPO=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
SRC_PATH = $(REPO)/src
SOURCES := $(wildcard $(SRC_PATH)/*.cpp)
HEADERS := $(wildcard $(SRC_PATH)/*.hpp)
OBJECTS := $(SOURCES:.cpp=.o)
TOOL_SRC_PATH := $(REPO)/tools
TOOL_SRC := $(wildcard $(TOOL_SRC_PATH)/*.cpp)
TOOLS := $(TOOL_SRC:.cpp=)
DAEMON_SRC = $(REPO)/daemon
PKGS := libuv libsodium
LD_FLAGS := $(shell pkg-config --libs $(PKGS))
INC_FLAGS := $(shell pkg-config --cflags $(PKGS)) -I $(REPO)/src
CXXFLAGS := -std=c++11 -Wall -Wextra $(INC_FLAGS)
ifeq ($(DEBUG),1)
CXXFLAGS += -g
endif
LIB = $(REPO)/libnntpchan.a
EXE = $(REPO)/nntpd
all: $(EXE) $(TOOLS)
$(LIB): $(OBJECTS)
$(AR) -r $(LIB) $(OBJECTS)
$(EXE): $(LIB)
$(CXX) $(CXXFLAGS) $(DAEMON_SRC)/main.cpp $(LIB) $(LD_FLAGS) -o $(EXE)
$(TOOL_SRC): $(LIB)
$(TOOLS): $(TOOL_SRC)
$(CXX) $(CXXFLAGS) $< $(LIB) $(LD_FLAGS) -o $@
build-test: $(LIB)
$(CXX) -o test $(CXXFLAGS) test.cpp $(LIB) $(LD_FLAGS)
test: build-test
./test
%.o: src/%.cpp
$(CXX) $(CXXFLAGS) -c -o $@
clean:
rm -f $(OBJECTS) $(LIB) $(EXE) $(TOOLS)
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
exit 0
@@ -0,0 +1,112 @@
#include "ini.hpp"
#include "crypto.hpp"
#include "storage.hpp"
#include "nntp_server.hpp"
#include "event.hpp"
#include "exec_frontend.hpp"
#include <vector>
#include <string>
int main(int argc, char * argv[]) {
if (argc != 2) {
std::cerr << "usage: " << argv[0] << " config.ini" << std::endl;
return 1;
}
nntpchan::Crypto crypto();
nntpchan::Mainloop loop;
nntpchan::NNTPServer nntp(loop);
std::string fname(argv[1]);
std::ifstream i(fname);
if(i.is_open()) {
INI::Parser conf(i);
std::vector<std::string> requiredSections = {"nntp", "articles"};
auto & level = conf.top();
for ( const auto & section : requiredSections ) {
if(level.sections.find(section) == level.sections.end()) {
std::cerr << "config file " << fname << " does not have required section: ";
std::cerr << section << std::endl;
return 1;
}
}
auto & storeconf = level.sections["articles"].values;
if (storeconf.find("store_path") == storeconf.end()) {
std::cerr << "storage section does not have 'store_path' value" << std::endl;
return 1;
}
nntp.SetStoragePath(storeconf["store_path"]);
auto & nntpconf = level.sections["nntp"].values;
if (nntpconf.find("bind") == nntpconf.end()) {
std::cerr << "nntp section does not have 'bind' value" << std::endl;
return 1;
}
if(nntpconf.find("instance_name") == nntpconf.end()) {
std::cerr << "nntp section lacks 'instance_name' value" << std::endl;
return 1;
}
nntp.SetInstanceName(nntpconf["instance_name"]);
if (nntpconf.find("authdb") != nntpconf.end()) {
nntp.SetLoginDB(nntpconf["authdb"]);
}
if ( level.sections.find("frontend") != level.sections.end()) {
// frontend enabled
auto & frontconf = level.sections["frontend"].values;
if (frontconf.find("type") == frontconf.end()) {
std::cerr << "frontend section provided but 'type' value not provided" << std::endl;
return 1;
}
auto ftype = frontconf["type"];
if (ftype == "exec") {
if (frontconf.find("exec") == frontconf.end()) {
std::cerr << "exec frontend specified but no 'exec' value provided" << std::endl;
return 1;
}
nntp.SetFrontend(new nntpchan::ExecFrontend(frontconf["exec"]));
} else {
std::cerr << "unknown frontend type '" << ftype << "'" << std::endl;
return 1;
}
}
auto & a = nntpconf["bind"];
try {
nntp.Bind(a);
} catch ( std::exception & ex ) {
std::cerr << "failed to bind: " << ex.what() << std::endl;
return 1;
}
std::cerr << "nntpd for " << nntp.InstanceName() << " bound to " << a << std::endl;
loop.Run();
} else {
std::cerr << "failed to open " << fname << std::endl;
return 1;
}
}
@@ -0,0 +1,7 @@
[nntp]
instance_name=nntp.server.tld
bind=[::]:1199
authdb=auth.txt
[articles]
store_path=./storage/
@@ -0,0 +1,234 @@
#include "base64.hpp"
// taken from i2pd
namespace i2p
{
namespace data
{
static void iT64Build(void);
/*
*
* BASE64 Substitution Table
* -------------------------
*
* Direct Substitution Table
*/
static const char T64[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/'
};
/*
* Reverse Substitution Table (built in run time)
*/
static char iT64[256];
static int isFirstTime = 1;
/*
* Padding
*/
static char P64 = '=';
/*
*
* ByteStreamToBase64
* ------------------
*
* Converts binary encoded data to BASE64 format.
*
*/
static size_t /* Number of bytes in the encoded buffer */
ByteStreamToBase64 (
const uint8_t * InBuffer, /* Input buffer, binary data */
size_t InCount, /* Number of bytes in the input buffer */
char * OutBuffer, /* output buffer */
size_t len /* length of output buffer */
)
{
unsigned char * ps;
unsigned char * pd;
unsigned char acc_1;
unsigned char acc_2;
int i;
int n;
int m;
size_t outCount;
ps = (unsigned char *)InBuffer;
n = InCount/3;
m = InCount%3;
if (!m)
outCount = 4*n;
else
outCount = 4*(n+1);
if (outCount > len) return 0;
pd = (unsigned char *)OutBuffer;
for ( i = 0; i<n; i++ ){
acc_1 = *ps++;
acc_2 = (acc_1<<4)&0x30;
acc_1 >>= 2; /* base64 digit #1 */
*pd++ = T64[acc_1];
acc_1 = *ps++;
acc_2 |= acc_1 >> 4; /* base64 digit #2 */
*pd++ = T64[acc_2];
acc_1 &= 0x0f;
acc_1 <<=2;
acc_2 = *ps++;
acc_1 |= acc_2>>6; /* base64 digit #3 */
*pd++ = T64[acc_1];
acc_2 &= 0x3f; /* base64 digit #4 */
*pd++ = T64[acc_2];
}
if ( m == 1 ){
acc_1 = *ps++;
acc_2 = (acc_1<<4)&0x3f; /* base64 digit #2 */
acc_1 >>= 2; /* base64 digit #1 */
*pd++ = T64[acc_1];
*pd++ = T64[acc_2];
*pd++ = P64;
*pd++ = P64;
}
else if ( m == 2 ){
acc_1 = *ps++;
acc_2 = (acc_1<<4)&0x3f;
acc_1 >>= 2; /* base64 digit #1 */
*pd++ = T64[acc_1];
acc_1 = *ps++;
acc_2 |= acc_1 >> 4; /* base64 digit #2 */
*pd++ = T64[acc_2];
acc_1 &= 0x0f;
acc_1 <<=2; /* base64 digit #3 */
*pd++ = T64[acc_1];
*pd++ = P64;
}
return outCount;
}
/*
*
* Base64ToByteStream
* ------------------
*
* Converts BASE64 encoded data to binary format. If input buffer is
* not properly padded, buffer of negative length is returned
*
*/
static
ssize_t /* Number of output bytes */
Base64ToByteStream (
const char * InBuffer, /* BASE64 encoded buffer */
size_t InCount, /* Number of input bytes */
uint8_t * OutBuffer, /* output buffer length */
size_t len /* length of output buffer */
)
{
unsigned char * ps;
unsigned char * pd;
unsigned char acc_1;
unsigned char acc_2;
int i;
int n;
int m;
size_t outCount;
if (isFirstTime) iT64Build();
n = InCount/4;
m = InCount%4;
if (InCount && !m)
outCount = 3*n;
else {
outCount = 0;
return 0;
}
ps = (unsigned char *)(InBuffer + InCount - 1);
while ( *ps-- == P64 ) outCount--;
ps = (unsigned char *)InBuffer;
if (outCount > len) return -1;
pd = OutBuffer;
auto endOfOutBuffer = OutBuffer + outCount;
for ( i = 0; i < n; i++ ){
acc_1 = iT64[*ps++];
acc_2 = iT64[*ps++];
acc_1 <<= 2;
acc_1 |= acc_2>>4;
*pd++ = acc_1;
if (pd >= endOfOutBuffer) break;
acc_2 <<= 4;
acc_1 = iT64[*ps++];
acc_2 |= acc_1 >> 2;
*pd++ = acc_2;
if (pd >= endOfOutBuffer) break;
acc_2 = iT64[*ps++];
acc_2 |= acc_1 << 6;
*pd++ = acc_2;
}
return outCount;
}
static size_t Base64EncodingBufferSize (const size_t input_size)
{
auto d = div (input_size, 3);
if (d.rem) d.quot++;
return 4*d.quot;
}
/*
*
* iT64
* ----
* Reverse table builder. P64 character is replaced with 0
*
*
*/
static void iT64Build()
{
int i;
isFirstTime = 0;
for ( i=0; i<256; i++ ) iT64[i] = -1;
for ( i=0; i<64; i++ ) iT64[(int)T64[i]] = i;
iT64[(int)P64] = 0;
}
}
}
namespace nntpchan
{
std::string B64Encode(const uint8_t * data, const std::size_t l)
{
std::string out;
out.resize(i2p::data::Base64EncodingBufferSize(l));
i2p::data::ByteStreamToBase64(data, l, &out[0], out.size());
return out;
}
bool B64Decode(const std::string & data, std::vector<uint8_t> & out)
{
out.resize(data.size());
if(i2p::data::Base64ToByteStream(data.c_str(), data.size(), &out[0], out.size()) == -1) return false;
out.shrink_to_fit();
return true;
}
}
@@ -0,0 +1,17 @@
#ifndef NNTPCHAN_BASE64_HPP
#define NNTPCHAN_BASE64_HPP
#include <string>
#include <vector>
namespace nntpchan
{
/** returns base64 encoded string */
std::string B64Encode(const uint8_t * data, const std::size_t l);
/** @brief returns true if decode was successful */
bool B64Decode(const std::string & data, std::vector<uint8_t> & out);
}
#endif
@@ -0,0 +1,21 @@
#include "buffer.hpp"
#include <cstring>
namespace nntpchan
{
WriteBuffer::WriteBuffer(const char * b, const size_t s)
{
char * buf = new char[s];
std::memcpy(buf, b, s);
this->b = uv_buf_init(buf, s);
w.data = this;
};
WriteBuffer::WriteBuffer(const std::string & s) : WriteBuffer(s.c_str(), s.size()) {}
WriteBuffer::~WriteBuffer()
{
delete [] b.base;
}
}
@@ -0,0 +1,19 @@
#ifndef NNTPCHAN_BUFFER_HPP
#define NNTPCHAN_BUFFER_HPP
#include <uv.h>
#include <string>
namespace nntpchan
{
struct WriteBuffer
{
uv_write_t w;
uv_buf_t b;
WriteBuffer(const std::string & s);
WriteBuffer(const char * b, const size_t s);
~WriteBuffer();
};
}
#endif
@@ -0,0 +1,20 @@
#include "crypto.hpp"
#include <sodium.h>
#include <cassert>
namespace nntpchan
{
void SHA512(const uint8_t * d, const std::size_t l, SHA512Digest & h)
{
crypto_hash(h.data(), d, l);
}
Crypto::Crypto()
{
assert(sodium_init() == 0);
}
Crypto::~Crypto()
{
}
}
@@ -0,0 +1,22 @@
#ifndef NNTPCHAN_CRYPTO_HPP
#define NNTPCHAN_CRYPTO_HPP
#include <sodium/crypto_hash.h>
#include <array>
namespace nntpchan
{
typedef std::array<uint8_t, crypto_hash_BYTES> SHA512Digest;
void SHA512(const uint8_t * d, std::size_t l, SHA512Digest & h);
/** global crypto initializer */
struct Crypto
{
Crypto();
~Crypto();
};
}
#endif
@@ -0,0 +1,27 @@
#include "event.hpp"
#include <cassert>
namespace nntpchan
{
Mainloop::Mainloop()
{
m_loop = uv_default_loop();
assert(uv_loop_init(m_loop) == 0);
}
Mainloop::~Mainloop()
{
uv_loop_close(m_loop);
}
void Mainloop::Stop()
{
uv_stop(m_loop);
}
void Mainloop::Run(uv_run_mode mode)
{
assert(uv_run(m_loop, mode) == 0);
}
}
@@ -0,0 +1,26 @@
#ifndef NNTPCHAN_EVENT_HPP
#define NNTPCHAN_EVENT_HPP
#include <uv.h>
namespace nntpchan
{
class Mainloop
{
public:
Mainloop();
~Mainloop();
operator uv_loop_t * () const { return m_loop; }
void Run(uv_run_mode mode = UV_RUN_DEFAULT);
void Stop();
private:
uv_loop_t * m_loop;
};
}
#endif
@@ -0,0 +1,57 @@
#include "exec_frontend.hpp"
#include <cstring>
#include <iostream>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
namespace nntpchan
{
ExecFrontend::ExecFrontend(const std::string & fname) :
m_exec(fname)
{
}
ExecFrontend::~ExecFrontend() {}
void ExecFrontend::ProcessNewMessage(const std::string & fpath)
{
Exec({"post", fpath});
}
bool ExecFrontend::AcceptsNewsgroup(const std::string & newsgroup)
{
return Exec({"newsgroup", newsgroup}) == 0;
}
bool ExecFrontend::AcceptsMessage(const std::string & msgid)
{
return Exec({"msgid", msgid}) == 0;
}
int ExecFrontend::Exec(std::deque<std::string> args)
{
// set up arguments
const char ** cargs = new char const *[args.size() +2];
std::size_t l = 0;
cargs[l++] = m_exec.c_str();
while (args.size()) {
cargs[l++] = args.front().c_str();
args.pop_front();
}
cargs[l] = 0;
int retcode = 0;
pid_t child = fork();
if(child) {
waitpid(child, &retcode, 0);
} else {
int r = execvpe(m_exec.c_str(),(char * const *) cargs, environ);
if ( r == -1 ) {
std::cout << strerror(errno) << std::endl;
exit( errno );
} else
exit(r);
}
return retcode;
}
}
@@ -0,0 +1,30 @@
#ifndef NNTPCHAN_EXEC_FRONTEND_HPP
#define NNTPCHAN_EXEC_FRONTEND_HPP
#include "frontend.hpp"
#include <deque>
namespace nntpchan
{
class ExecFrontend : public Frontend
{
public:
ExecFrontend(const std::string & exe);
~ExecFrontend();
void ProcessNewMessage(const std::string & fpath);
bool AcceptsNewsgroup(const std::string & newsgroup);
bool AcceptsMessage(const std::string & msgid);
private:
int Exec(std::deque<std::string> args);
private:
std::string m_exec;
};
}
#endif
@@ -0,0 +1,25 @@
#ifndef NNTPCHAN_FRONTEND_HPP
#define NNTPCHAN_FRONTEND_HPP
#include <string>
namespace nntpchan
{
/** @brief nntpchan frontend ui interface */
class Frontend
{
public:
virtual ~Frontend() {}
/** @brief process an inbound message stored at fpath that we have accepted. */
virtual void ProcessNewMessage(const std::string & fpath) = 0;
/** @brief return true if we take posts in a newsgroup */
virtual bool AcceptsNewsgroup(const std::string & newsgroup) = 0;
/** @brief return true if we will accept a message given its message-id */
virtual bool AcceptsMessage(const std::string & msgid) = 0;
};
}
#endif
@@ -0,0 +1,6 @@
#ifndef NNTPCHAN_HTTP_HPP
#define NNTPCHAN_HTTP_HPP
#endif
@@ -0,0 +1,5 @@
#ifndef NNTPCHAN_HTTP_CLIENT_HPP
#define NNTPCHAN_HTTP_CLIENT_HPP
#endif
@@ -0,0 +1,6 @@
#ifndef NNTPCHAN_HTTP_SERVER_HPP
#define NNTPCHAN_HTTP_SERVER_HPP
#endif
@@ -0,0 +1,186 @@
/**
* The MIT License (MIT)
* Copyright (c) <2015> <carriez.md@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#ifndef INI_HPP
#define INI_HPP
#include <cassert>
#include <map>
#include <list>
#include <stdexcept>
#include <string>
#include <cstring>
#include <iostream>
#include <fstream>
namespace INI {
struct Level
{
Level() : parent(NULL), depth(0) {}
Level(Level* p) : parent(p), depth(0) {}
typedef std::map<std::string, std::string> value_map_t;
typedef std::map<std::string, Level> section_map_t;
typedef std::list<value_map_t::const_iterator> values_t;
typedef std::list<section_map_t::const_iterator> sections_t;
value_map_t values;
section_map_t sections;
values_t ordered_values; // original order in the ini file
sections_t ordered_sections;
Level* parent;
size_t depth;
const std::string& operator[](const std::string& name) { return values[name]; }
Level& operator()(const std::string& name) { return sections[name]; }
};
class Parser
{
public:
Parser(const char* fn);
Parser(std::istream& f) : f_(&f), ln_(0) { parse(top_); }
Level& top() { return top_; }
void dump(std::ostream& s) { dump(s, top(), ""); }
private:
void dump(std::ostream& s, const Level& l, const std::string& sname);
void parse(Level& l);
void parseSLine(std::string& sname, size_t& depth);
void err(const char* s);
private:
Level top_;
std::ifstream f0_;
std::istream* f_;
std::string line_;
size_t ln_;
};
inline void
Parser::err(const char* s)
{
char buf[256];
sprintf(buf, "%s on line #%ld", s, ln_);
throw std::runtime_error(buf);
}
inline std::string trim(const std::string& s)
{
char p[] = " \t\r\n";
long sp = 0;
long ep = s.length() - 1;
for (; sp <= ep; ++sp)
if (!strchr(p, s[sp])) break;
for (; ep >= 0; --ep)
if (!strchr(p, s[ep])) break;
return s.substr(sp, ep-sp+1);
}
inline
Parser::Parser(const char* fn) : f0_(fn), f_(&f0_), ln_(0)
{
if (!f0_)
throw std::runtime_error(std::string("failed to open file: ") + fn);
parse(top_);
}
inline void
Parser::parseSLine(std::string& sname, size_t& depth)
{
depth = 0;
for (; depth < line_.length(); ++depth)
if (line_[depth] != '[') break;
sname = line_.substr(depth, line_.length() - 2*depth);
}
inline void
Parser::parse(Level& l)
{
while (std::getline(*f_, line_)) {
++ln_;
if (line_[0] == '#' || line_[0] == ';') continue;
line_ = trim(line_);
if (line_.empty()) continue;
if (line_[0] == '[') {
size_t depth;
std::string sname;
parseSLine(sname, depth);
Level* lp = NULL;
Level* parent = &l;
if (depth > l.depth + 1)
err("section with wrong depth");
if (l.depth == depth-1)
lp = &l.sections[sname];
else {
lp = l.parent;
size_t n = l.depth - depth;
for (size_t i = 0; i < n; ++i) lp = lp->parent;
parent = lp;
lp = &lp->sections[sname];
}
if (lp->depth != 0)
err("duplicate section name on the same level");
if (!lp->parent) {
lp->depth = depth;
lp->parent = parent;
}
parent->ordered_sections.push_back(parent->sections.find(sname));
parse(*lp);
} else {
size_t n = line_.find('=');
if (n == std::string::npos)
err("no '=' found");
std::pair<Level::value_map_t::const_iterator, bool> res =
l.values.insert(std::make_pair(trim(line_.substr(0, n)),
trim(line_.substr(n+1, line_.length()-n-1))));
if (!res.second)
err("duplicated key found");
l.ordered_values.push_back(res.first);
}
}
}
inline void
Parser::dump(std::ostream& s, const Level& l, const std::string& sname)
{
if (!sname.empty()) s << '\n';
for (size_t i = 0; i < l.depth; ++i) s << '[';
if (!sname.empty()) s << sname;
for (size_t i = 0; i < l.depth; ++i) s << ']';
if (!sname.empty()) s << std::endl;
for (Level::values_t::const_iterator it = l.ordered_values.begin(); it != l.ordered_values.end(); ++it)
s << (*it)->first << '=' << (*it)->second << std::endl;
for (Level::sections_t::const_iterator it = l.ordered_sections.begin(); it != l.ordered_sections.end(); ++it) {
assert((*it)->second.depth == l.depth+1);
dump(s, (*it)->second, (*it)->first);
}
}
}
#endif // INI_HPP
@@ -0,0 +1,39 @@
#include "line.hpp"
namespace nntpchan {
LineReader::LineReader(size_t limit) : m_close(false), lineLimit(limit) {}
void LineReader::Data(const char * data, ssize_t l)
{
if(l <= 0) return;
// process leftovers
std::size_t idx = 0;
std::size_t pos = 0;
while(l-- > 0) {
char c = data[idx++];
if(c == '\n') {
OnLine(data, pos);
pos = 0;
data += idx;
} else if (c == '\r' && data[idx] == '\n') {
OnLine(data, pos);
data += idx + 1;
pos = 0;
} else {
pos ++;
}
}
}
void LineReader::OnLine(const char *d, const size_t l)
{
std::string line(d, l);
HandleLine(line);
}
bool LineReader::ShouldClose()
{
return m_close;
}
}
@@ -0,0 +1,34 @@
#ifndef NNTPCHAN_LINE_HPP
#define NNTPCHAN_LINE_HPP
#include "server.hpp"
#include <stdint.h>
namespace nntpchan
{
/** @brief a buffered line reader */
class LineReader
{
public:
LineReader(size_t lineLimit);
/** @brief queue inbound data from connection */
void Data(const char * data, ssize_t s);
/** implements IConnHandler */
virtual bool ShouldClose();
protected:
/** @brief handle a line from the client */
virtual void HandleLine(const std::string & line) = 0;
private:
void OnLine(const char * d, const size_t l);
std::string m_leftovers;
bool m_close;
const size_t lineLimit;
};
}
#endif
@@ -0,0 +1,28 @@
#include "message.hpp"
namespace nntpchan
{
bool IsValidMessageID(const std::string & msgid)
{
if(msgid[0] != '<') return false;
if(msgid[msgid.size()-1] != '>') return false;
auto itr = msgid.begin() + 1;
auto end = msgid.end() - 1;
bool atfound = false;
while(itr != end) {
auto c = *itr;
++itr;
if(atfound && c == '@') return false;
if(c == '@') {
atfound = true;
continue;
}
if (c == '$' || c == '_' || c == '-' || c == '.') continue;
if (c >= '0' && c <= '9') continue;
if (c >= 'A' && c <= 'Z') continue;
if (c >= 'a' && c <= 'z') continue;
return false;
}
return true;
}
}
@@ -0,0 +1,34 @@
#ifndef NNTPCHAN_MESSAGE_HPP
#define NNTPCHAN_MESSAGE_HPP
#include <string>
#include <vector>
#include <map>
#include <functional>
namespace nntpchan
{
bool IsValidMessageID(const std::string & msgid);
typedef std::pair<std::string, std::string> MessageHeader;
typedef std::map<std::string, std::string> MIMEPartHeader;
typedef std::function<bool(const MessageHeader &)> MessageHeaderFilter;
typedef std::function<bool(const MIMEPartHeader &)> MIMEPartFilter;
/**
read MIME message from i,
filter each header with h,
filter each part with p,
store result in o
return true if we read the whole message, return false if there is remaining
*/
bool StoreMIMEMessage(std::istream & i, MessageHeaderFilter h, MIMEPartHeader p, std::ostream & o);
}
#endif
@@ -0,0 +1,262 @@
/*
Author: José Bollo <jobol@nonadev.net>
Author: José Bollo <jose.bollo@iot.bzh>
https://gitlab.com/jobol/mustach
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include "mustache.hpp"
#define NAME_LENGTH_MAX 1024
#define DEPTH_MAX 256
namespace nntpchan
{
namespace mustache
{
static int getpartial(struct mustach_itf *itf, void *closure, const char *name, char **result)
{
int rc;
FILE *file;
size_t size;
*result = NULL;
file = open_memstream(result, &size);
if (file == NULL)
rc = MUSTACH_ERROR_SYSTEM;
else {
rc = itf->put(closure, name, 0, file);
if (rc == 0)
/* adds terminating null */
rc = fputc(0, file) ? MUSTACH_ERROR_SYSTEM : 0;
fclose(file);
if (rc < 0) {
free(*result);
*result = NULL;
}
}
return rc;
}
static int process(const char *templ, struct mustach_itf *itf, void *closure, FILE *file, const char *opstr, const char *clstr)
{
char name[NAME_LENGTH_MAX + 1], *partial, c;
const char *beg, *term;
struct { const char *name, *again; size_t length; int emit, entered; } stack[DEPTH_MAX];
size_t oplen, cllen, len, l;
int depth, rc, emit;
emit = 1;
oplen = strlen(opstr);
cllen = strlen(clstr);
depth = 0;
for(;;) {
beg = strstr(templ, opstr);
if (beg == NULL) {
/* no more mustach */
if (emit)
fwrite(templ, strlen(templ), 1, file);
return depth ? MUSTACH_ERROR_UNEXPECTED_END : 0;
}
if (emit)
fwrite(templ, (size_t)(beg - templ), 1, file);
beg += oplen;
term = strstr(beg, clstr);
if (term == NULL)
return MUSTACH_ERROR_UNEXPECTED_END;
templ = term + cllen;
len = (size_t)(term - beg);
c = *beg;
switch(c) {
case '!':
case '=':
break;
case '{':
for (l = 0 ; clstr[l] == '}' ; l++);
if (clstr[l]) {
if (!len || beg[len-1] != '}')
return MUSTACH_ERROR_BAD_UNESCAPE_TAG;
len--;
} else {
if (term[l] != '}')
return MUSTACH_ERROR_BAD_UNESCAPE_TAG;
templ++;
}
c = '&';
case '^':
case '#':
case '/':
case '&':
case '>':
#if !defined(NO_EXTENSION_FOR_MUSTACH) && !defined(NO_COLON_EXTENSION_FOR_MUSTACH)
case ':':
#endif
beg++; len--;
default:
while (len && isspace(beg[0])) { beg++; len--; }
while (len && isspace(beg[len-1])) len--;
if (len == 0)
return MUSTACH_ERROR_EMPTY_TAG;
if (len > NAME_LENGTH_MAX)
return MUSTACH_ERROR_TAG_TOO_LONG;
memcpy(name, beg, len);
name[len] = 0;
break;
}
switch(c) {
case '!':
/* comment */
/* nothing to do */
break;
case '=':
/* defines separators */
if (len < 5 || beg[len - 1] != '=')
return MUSTACH_ERROR_BAD_SEPARATORS;
beg++;
len -= 2;
for (l = 0; l < len && !isspace(beg[l]) ; l++);
if (l == len)
return MUSTACH_ERROR_BAD_SEPARATORS;
opstr = strndupa(beg, l);
while (l < len && isspace(beg[l])) l++;
if (l == len)
return MUSTACH_ERROR_BAD_SEPARATORS;
clstr = strndupa(beg + l, len - l);
oplen = strlen(opstr);
cllen = strlen(clstr);
break;
case '^':
case '#':
/* begin section */
if (depth == DEPTH_MAX)
return MUSTACH_ERROR_TOO_DEPTH;
rc = emit;
if (rc) {
rc = itf->enter(closure, name);
if (rc < 0)
return rc;
}
stack[depth].name = beg;
stack[depth].again = templ;
stack[depth].length = len;
stack[depth].emit = emit;
stack[depth].entered = rc;
if ((c == '#') == (rc == 0))
emit = 0;
depth++;
break;
case '/':
/* end section */
if (depth-- == 0 || len != stack[depth].length || memcmp(stack[depth].name, name, len))
return MUSTACH_ERROR_CLOSING;
rc = emit && stack[depth].entered ? itf->next(closure) : 0;
if (rc < 0)
return rc;
if (rc) {
templ = stack[depth++].again;
} else {
emit = stack[depth].emit;
if (emit && stack[depth].entered)
itf->leave(closure);
}
break;
case '>':
/* partials */
if (emit) {
rc = getpartial(itf, closure, name, &partial);
if (rc == 0) {
rc = process(partial, itf, closure, file, opstr, clstr);
free(partial);
}
if (rc < 0)
return rc;
}
break;
default:
/* replacement */
if (emit) {
rc = itf->put(closure, name, c != '&', file);
if (rc < 0)
return rc;
}
break;
}
}
}
int fmustach(const char *templ, struct mustach_itf *itf, void *closure, FILE *file)
{
int rc = itf->start ? itf->start(closure) : 0;
if (rc == 0)
rc = process(templ, itf, closure, file, "{{", "}}");
return rc;
}
int fdmustach(const char *templ, struct mustach_itf *itf, void *closure, int fd)
{
int rc;
FILE *file;
file = fdopen(fd, "w");
if (file == NULL) {
rc = MUSTACH_ERROR_SYSTEM;
errno = ENOMEM;
} else {
rc = fmustach(templ, itf, closure, file);
fclose(file);
}
return rc;
}
int mustach(const char *templ, struct mustach_itf *itf, void *closure, char **result, size_t *size)
{
int rc;
FILE *file;
size_t s;
*result = NULL;
if (size == NULL)
size = &s;
file = open_memstream(result, size);
if (file == NULL) {
rc = MUSTACH_ERROR_SYSTEM;
errno = ENOMEM;
} else {
rc = fmustach(templ, itf, closure, file);
if (rc == 0)
/* adds terminating null */
rc = fputc(0, file) ? MUSTACH_ERROR_SYSTEM : 0;
fclose(file);
if (rc >= 0)
/* removes terminating null of the length */
(*size)--;
else {
free(*result);
*result = NULL;
*size = 0;
}
}
return rc;
}
}
}
@@ -0,0 +1,96 @@
#ifndef NNTPCHAN_MUSTACHE
#define NNTPCHAN_MUSTACHE
/*
Author: José Bollo <jobol@nonadev.net>
Author: José Bollo <jose.bollo@iot.bzh>
https://gitlab.com/jobol/mustach
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#define MUSTACH_OK 0
#define MUSTACH_ERROR_SYSTEM -1
#define MUSTACH_ERROR_UNEXPECTED_END -2
#define MUSTACH_ERROR_EMPTY_TAG -3
#define MUSTACH_ERROR_TAG_TOO_LONG -4
#define MUSTACH_ERROR_BAD_SEPARATORS -5
#define MUSTACH_ERROR_TOO_DEPTH -6
#define MUSTACH_ERROR_CLOSING -7
#define MUSTACH_ERROR_BAD_UNESCAPE_TAG -8
#include <cstdio>
namespace nntpchan
{
namespace mustache
{
/**
* mustach_itf - interface for callbacks
*
* All of this function should return a negative value to stop
* the mustache processing. The returned negative value will be
* then returned to the caller of mustach as is.
*
* The functions enter and next should return 0 or 1.
*
* All other functions should normally return 0.
*
* @start: Starts the mustach processing of the closure
* 'start' is optional (can be NULL)
*
* @put: Writes the value of 'name' to 'file' with 'escape' or not
*
* @enter: Enters the section of 'name' if possible.
* Musts return 1 if entered or 0 if not entered.
* When 1 is returned, the function 'leave' will always be called.
* Conversely 'leave' is never called when enter returns 0 or
* a negative value.
* When 1 is returned, the function must activate the first
* item of the section.
*
* @next: Activates the next item of the section if it exists.
* Musts return 1 when the next item is activated.
* Musts return 0 when there is no item to activate.
*
* @leave: Leaves the last entered section
*/
struct mustach_itf {
int (*start)(void *closure);
int (*put)(void *closure, const char *name, int escape, FILE *file);
int (*enter)(void *closure, const char *name);
int (*next)(void *closure);
int (*leave)(void *closure);
};
/**
* fmustach - Renders the mustache 'template' in 'file' for 'itf' and 'closure'.
*
* @template: the template string to instanciate
* @itf: the interface to the functions that mustach calls
* @closure: the closure to pass to functions called
* @file: the file where to write the result
*
* Returns 0 in case of success, -1 with errno set in case of system error
* a other negative value in case of error.
*/
int fmustach(const char *templ, struct mustach_itf *itf, void *closure, FILE *file);
}
}
#endif
@@ -0,0 +1,44 @@
#include "net.hpp"
#include <uv.h>
#include <sstream>
#include <stdexcept>
#include <cstring>
namespace nntpchan
{
std::string NetAddr::to_string()
{
std::string str("invalid");
const size_t s = 128;
char * buff = new char[s];
if(uv_ip6_name(&addr, buff, s) == 0) {
str = std::string(buff);
delete [] buff;
}
std::stringstream ss;
ss << "[" << str << "]:" << ntohs(addr.sin6_port);
return ss.str();
}
NetAddr::NetAddr()
{
std::memset(&addr, 0, sizeof(addr));
}
NetAddr ParseAddr(const std::string & addr)
{
NetAddr saddr;
auto n = addr.rfind("]:");
if (n == std::string::npos) {
throw std::runtime_error("invalid address: "+addr);
}
if (addr[0] != '[') {
throw std::runtime_error("invalid address: "+addr);
}
auto p = addr.substr(n+2);
int port = std::atoi(p.c_str());
auto a = addr.substr(0, n);
uv_ip6_addr(a.c_str(), port, &saddr.addr);
return saddr;
}
}
@@ -0,0 +1,23 @@
#ifndef NNTPCHAN_NET_HPP
#define NNTPCHAN_NET_HPP
#include <sys/types.h>
#include <netinet/in.h>
#include <string>
namespace nntpchan
{
struct NetAddr
{
NetAddr();
sockaddr_in6 addr;
operator sockaddr * () { return (sockaddr *) &addr; }
operator const sockaddr * () const { return (sockaddr *) &addr; }
std::string to_string();
};
NetAddr ParseAddr(const std::string & addr);
}
#endif
@@ -0,0 +1,99 @@
#include "nntp_auth.hpp"
#include "crypto.hpp"
#include "base64.hpp"
#include <array>
#include <iostream>
#include <fstream>
namespace nntpchan
{
HashedCredDB::HashedCredDB() : LineReader(1024) {}
bool HashedCredDB::CheckLogin(const std::string & user, const std::string & passwd)
{
std::unique_lock<std::mutex> lock(m_access);
m_found = false;
m_user = user;
m_passwd = passwd;
m_instream->seekg(0, std::ios::end);
const auto l = m_instream->tellg();
m_instream->seekg(0, std::ios::beg);
char * buff = new char[l];
// read file
m_instream->read(buff, l);
Data(buff, l);
delete [] buff;
return m_found;
}
bool HashedCredDB::ProcessLine(const std::string & line)
{
// strip comments
auto comment = line.find("#");
std::string part = line;
for (; comment != std::string::npos; comment = part.find("#")) {
if(comment)
part = part.substr(0, comment);
else break;
}
if(!part.size()) return false; // empty line after comments
auto idx = part.find(":");
if (idx == std::string::npos) return false; // bad format
if (m_user != part.substr(0, idx)) return false; // username mismatch
part = part.substr(idx+1);
idx = part.find(":");
if (idx == std::string::npos) return false; // bad format
std::string cred = part.substr(0, idx);
std::string salt = part.substr(idx+1);
return Hash(m_passwd, salt) == cred;
}
void HashedCredDB::HandleLine(const std::string &line)
{
if(m_found) return;
if(ProcessLine(line))
m_found = true;
}
void HashedCredDB::SetStream(std::istream * s)
{
m_instream = s;
}
std::string HashedCredDB::Hash(const std::string & data, const std::string & salt)
{
SHA512Digest h;
std::string d = data + salt;
SHA512((const uint8_t*)d.c_str(), d.size(), h);
return B64Encode(h.data(), h.size());
}
HashedFileDB::HashedFileDB(const std::string & fname) :
m_fname(fname),
f(nullptr)
{
}
HashedFileDB::~HashedFileDB()
{
}
void HashedFileDB::Close()
{
if(f.is_open())
f.close();
}
bool HashedFileDB::Open()
{
if(!f.is_open())
f.open(m_fname);
if(f.is_open()) {
SetStream(&f);
return true;
}
return false;
}
}
@@ -0,0 +1,58 @@
#ifndef NNTPCHAN_NNTP_AUTH_HPP
#define NNTPCHAN_NNTP_AUTH_HPP
#include <string>
#include <iostream>
#include <fstream>
#include <mutex>
#include "line.hpp"
namespace nntpchan
{
/** @brief nntp credential db interface */
class NNTPCredentialDB
{
public:
/** @brief open connection to database, return false on error otherwise return true */
virtual bool Open() = 0;
/** @brief close connection to database */
virtual void Close() = 0;
/** @brief return true if username password combo is correct */
virtual bool CheckLogin(const std::string & user, const std::string & passwd) = 0;
virtual ~NNTPCredentialDB() {}
};
/** @brief nntp credential db using hashed+salted passwords */
class HashedCredDB : public NNTPCredentialDB, public LineReader
{
public:
HashedCredDB();
bool CheckLogin(const std::string & user, const std::string & passwd);
protected:
void SetStream(std::istream * i);
std::string Hash(const std::string & data, const std::string & salt);
void HandleLine(const std::string & line);
private:
bool ProcessLine(const std::string & line);
std::mutex m_access;
std::string m_user, m_passwd;
bool m_found;
/** return true if we have a line that matches this username / password combo */
std::istream * m_instream;
};
class HashedFileDB : public HashedCredDB
{
public:
HashedFileDB(const std::string & fname);
~HashedFileDB();
bool Open();
void Close();
private:
std::string m_fname;
std::ifstream f;
};
}
#endif
@@ -0,0 +1,217 @@
#include "nntp_handler.hpp"
#include "message.hpp"
#include <algorithm>
#include <cctype>
#include <cstring>
#include <string>
#include <sstream>
#include <iostream>
namespace nntpchan
{
NNTPServerHandler::NNTPServerHandler(const std::string & storage) :
LineReader(1024),
m_article(nullptr),
m_auth(nullptr),
m_store(storage),
m_authed(false),
m_state(eStateReadCommand)
{
}
NNTPServerHandler::~NNTPServerHandler()
{
if(m_auth) delete m_auth;
}
void NNTPServerHandler::HandleLine(const std::string &line)
{
if(m_state == eStateReadCommand)
{
std::deque<std::string> command;
std::istringstream s;
s.str(line);
for (std::string part; std::getline(s, part, ' '); ) {
if(part.size()) command.push_back(std::string(part));
}
if(command.size())
HandleCommand(command);
else
QueueLine("501 Syntax error");
}
else if(m_state == eStateStoreArticle)
{
std::string l = line + "\r\n";
OnData(l.c_str(), l.size());
}
else
{
std::cerr << "invalid state" << std::endl;
}
}
void NNTPServerHandler::OnData(const char * data, ssize_t l)
{
if(l <= 0 ) return;
if(m_state == eStateStoreArticle)
{
const char * end = strstr(data, "\r\n.\r\n");
if(end)
{
std::size_t diff = end - data ;
if(m_article)
m_article->write(data, diff+2);
ArticleObtained();
diff += 5;
Data(end+5, l-diff);
return;
}
if(m_article)
m_article->write(data, l);
}
else
Data(data, l);
}
void NNTPServerHandler::HandleCommand(const std::deque<std::string> & command)
{
auto cmd = command[0];
std::transform(cmd.begin(), cmd.end(), cmd.begin(), ::toupper);
std::size_t cmdlen = command.size();
for(const auto & part : command)
std::cerr << " " << part;
std::cerr << std::endl;
if (cmd == "QUIT") {
Quit();
return;
}
else if (cmd[0] == '5')
{
return;
}
else if (cmd == "MODE" ) {
if(cmdlen == 2) {
// set mode
SwitchMode(command[1]);
} else if(cmdlen) {
// too many arguments
QueueLine("500 too many arguments");
} else {
// get mode
QueueLine("500 wrong arguments");
}
} else if(cmd == "CAPABILITIES") {
QueueLine("101 I support the following:");
QueueLine("READER");
QueueLine("IMPLEMENTATION nntpchan-daemon");
QueueLine("VERSION 2");
QueueLine("STREAMING");
QueueLine(".");
} else if (cmd == "CHECK") {
if(cmdlen == 2) {
const std::string & msgid = command[1];
if(IsValidMessageID(msgid) && m_store.Accept(msgid))
{
QueueLine("238 "+msgid);
return;
}
QueueLine("438 "+msgid);
}
else
QueueLine("501 syntax error");
} else if (cmd == "TAKETHIS") {
if (cmdlen == 2)
{
const std::string & msgid = command[1];
if(m_store.Accept(msgid))
{
m_article = m_store.OpenWrite(msgid);
}
m_articleName = msgid;
EnterState(eStateStoreArticle);
return;
}
QueueLine("501 invalid syntax");
} else {
// unknown command
QueueLine("500 Unknown Command");
}
}
void NNTPServerHandler::ArticleObtained()
{
if(m_article)
{
m_article->flush();
m_article->close();
delete m_article;
m_article = nullptr;
QueueLine("239 "+m_articleName);
std::cerr << "stored " << m_articleName << std::endl;
}
else
QueueLine("439 "+m_articleName);
m_articleName = "";
EnterState(eStateReadCommand);
}
void NNTPServerHandler::SwitchMode(const std::string & mode)
{
std::string m = mode;
std::transform(m.begin(), m.end(), m.begin(), ::toupper);
if (m == "READER") {
m_mode = m;
if(PostingAllowed()) {
QueueLine("200 Posting is permitted yo");
} else {
QueueLine("201 Posting is not permitted yo");
}
} else if (m == "STREAM") {
m_mode = m;
if (PostingAllowed()) {
QueueLine("203 Streaming enabled");
} else {
QueueLine("483 Streaming Denied");
}
} else {
// unknown mode
QueueLine("500 Unknown mode");
}
}
void NNTPServerHandler::EnterState(State st)
{
std::cerr << "enter state " << st << std::endl;
m_state = st;
}
void NNTPServerHandler::Quit()
{
EnterState(eStateQuit);
QueueLine("205 quitting");
}
bool NNTPServerHandler::ShouldClose()
{
return m_state == eStateQuit;
}
bool NNTPServerHandler::PostingAllowed()
{
return m_authed || m_auth == nullptr;
}
void NNTPServerHandler::Greet()
{
if(PostingAllowed())
QueueLine("200 Posting allowed");
else
QueueLine("201 Posting not allowed");
}
void NNTPServerHandler::SetAuth(NNTPCredentialDB *creds)
{
if(m_auth) delete m_auth;
m_auth = creds;
}
}
@@ -0,0 +1,62 @@
#ifndef NNTPCHAN_NNTP_HANDLER_HPP
#define NNTPCHAN_NNTP_HANDLER_HPP
#include <deque>
#include <string>
#include "line.hpp"
#include "nntp_auth.hpp"
#include "storage.hpp"
namespace nntpchan
{
class NNTPServerHandler : public LineReader, public IConnHandler
{
public:
NNTPServerHandler(const std::string & storage);
~NNTPServerHandler();
virtual bool ShouldClose();
void SetAuth(NNTPCredentialDB * creds);
virtual void OnData(const char *, ssize_t);
void Greet();
protected:
void HandleLine(const std::string & line);
void HandleCommand(const std::deque<std::string> & command);
private:
enum State {
eStateReadCommand,
eStateStoreArticle,
eStateQuit
};
private:
void EnterState(State st);
void ArticleObtained();
// handle quit command, this queues a reply
void Quit();
// switch nntp modes, this queues a reply
void SwitchMode(const std::string & mode);
bool PostingAllowed();
private:
std::string m_articleName;
std::fstream * m_article;
NNTPCredentialDB * m_auth;
ArticleStorage m_store;
std::string m_mode;
bool m_authed;
State m_state;
};
}
#endif
@@ -0,0 +1,87 @@
#include "nntp_server.hpp"
#include "nntp_auth.hpp"
#include "nntp_handler.hpp"
#include "net.hpp"
#include <cassert>
#include <iostream>
#include <sstream>
namespace nntpchan
{
NNTPServer::NNTPServer(uv_loop_t * loop) : Server(loop), m_frontend(nullptr) {}
NNTPServer::~NNTPServer()
{
if (m_frontend) delete m_frontend;
}
IServerConn * NNTPServer::CreateConn(uv_stream_t * s)
{
NNTPCredentialDB * creds = nullptr;
std::ifstream i;
i.open(m_logindbpath);
if(i.is_open()) creds = new HashedFileDB(m_logindbpath);
NNTPServerHandler * handler = new NNTPServerHandler(m_storagePath);
if(creds)
handler->SetAuth(creds);
NNTPServerConn * conn = new NNTPServerConn(GetLoop(), s, this, handler);
return conn;
}
void NNTPServer::SetLoginDB(const std::string path)
{
m_logindbpath = path;
}
void NNTPServer::SetStoragePath(const std::string & path)
{
m_storagePath = path;
}
void NNTPServer::SetInstanceName(const std::string & name)
{
m_servername = name;
}
std::string NNTPServer::InstanceName() const
{
return m_servername;
}
void NNTPServer::SetFrontend(Frontend * f)
{
if(m_frontend) delete m_frontend;
m_frontend = f;
}
void NNTPServer::OnAcceptError(int status)
{
std::cerr << "nntpserver::accept() " << uv_strerror(status) << std::endl;
}
void NNTPServerConn::SendNextReply()
{
IConnHandler * handler = GetHandler();
while(handler->HasNextLine()) {
auto line = handler->GetNextLine();
SendString(line + "\n");
}
}
void NNTPServerConn::Greet()
{
IConnHandler * handler = GetHandler();
handler->Greet();
SendNextReply();
}
}
@@ -0,0 +1,62 @@
#ifndef NNTPCHAN_NNTP_SERVER_HPP
#define NNTPCHAN_NNTP_SERVER_HPP
#include <uv.h>
#include <string>
#include <deque>
#include "frontend.hpp"
#include "server.hpp"
namespace nntpchan
{
class NNTPServer : public Server
{
public:
NNTPServer(uv_loop_t * loop);
virtual ~NNTPServer();
void SetStoragePath(const std::string & path);
void SetLoginDB(const std::string path);
void SetInstanceName(const std::string & name);
std::string InstanceName() const;
void SetFrontend(Frontend * f);
void Close();
virtual IServerConn * CreateConn(uv_stream_t * s);
virtual void OnAcceptError(int status);
private:
std::string m_logindbpath;
std::string m_storagePath;
std::string m_servername;
Frontend * m_frontend;
};
class NNTPServerConn : public IServerConn
{
public:
NNTPServerConn(uv_loop_t * l, uv_stream_t * s, Server * parent, IConnHandler * h) : IServerConn(l, s, parent, h) {}
virtual bool IsTimedOut() { return false; };
/** @brief send next queued reply */
virtual void SendNextReply();
virtual void Greet();
};
}
#endif
@@ -0,0 +1,140 @@
#include "buffer.hpp"
#include "server.hpp"
#include "net.hpp"
#include <cassert>
#include <iostream>
namespace nntpchan
{
Server::Server(uv_loop_t * loop)
{
m_loop = loop;
uv_tcp_init(m_loop, &m_server);
m_server.data = this;
}
void Server::Close()
{
std::cout << "Close server" << std::endl;
uv_close((uv_handle_t*)&m_server, [](uv_handle_t * s) {
Server * self = (Server*)s->data;
if (self) delete self;
s->data = nullptr;
});
}
void Server::Bind(const std::string & addr)
{
auto saddr = ParseAddr(addr);
assert(uv_tcp_bind(*this, saddr, 0) == 0);
auto cb = [] (uv_stream_t * s, int status) {
Server * self = (Server *) s->data;
self->OnAccept(s, status);
};
assert(uv_listen(*this, 5, cb) == 0);
}
void Server::OnAccept(uv_stream_t * s, int status)
{
if(status < 0) {
OnAcceptError(status);
return;
}
IServerConn * conn = CreateConn(s);
assert(conn);
m_conns.push_back(conn);
conn->Greet();
}
void Server::RemoveConn(IServerConn * conn)
{
auto itr = m_conns.begin();
while(itr != m_conns.end())
{
if(*itr == conn)
itr = m_conns.erase(itr);
else
++itr;
}
}
void IConnHandler::QueueLine(const std::string & line)
{
m_sendlines.push_back(line);
}
bool IConnHandler::HasNextLine()
{
return m_sendlines.size() > 0;
}
std::string IConnHandler::GetNextLine()
{
std::string line = m_sendlines[0];
m_sendlines.pop_front();
return line;
}
IServerConn::IServerConn(uv_loop_t * l, uv_stream_t * st, Server * parent, IConnHandler * h)
{
m_loop = l;
m_parent = parent;
m_handler = h;
uv_tcp_init(l, &m_conn);
m_conn.data = this;
uv_accept(st, (uv_stream_t*) &m_conn);
uv_read_start((uv_stream_t*) &m_conn, [] (uv_handle_t * h, size_t s, uv_buf_t * b) {
IServerConn * self = (IServerConn*) h->data;
if(self == nullptr) return;
b->base = self->m_readbuff;
if (s > sizeof(self->m_readbuff))
b->len = sizeof(self->m_readbuff);
else
b->len = s;
}, [] (uv_stream_t * s, ssize_t nread, const uv_buf_t * b) {
IServerConn * self = (IServerConn*) s->data;
if(self == nullptr) return;
if(nread > 0) {
self->m_handler->OnData(b->base, nread);
self->SendNextReply();
if(self->m_handler->ShouldClose())
self->Close();
} else {
if (nread != UV_EOF) {
std::cerr << "error in nntp server conn alloc: ";
std::cerr << uv_strerror(nread);
std::cerr << std::endl;
}
// got eof or error
self->Close();
}
});
}
IServerConn::~IServerConn()
{
delete m_handler;
}
void IServerConn::SendString(const std::string & str)
{
WriteBuffer * b = new WriteBuffer(str);
uv_write(&b->w, (uv_stream_t*)&m_conn, &b->b, 1, [](uv_write_t * w, int status) {
(void) status;
WriteBuffer * wb = (WriteBuffer *) w->data;
if(wb)
delete wb;
});
}
void IServerConn::Close()
{
m_parent->RemoveConn(this);
uv_close((uv_handle_t*)&m_conn, [] (uv_handle_t * s) {
IServerConn * self = (IServerConn*) s->data;
if(self)
delete self;
s->data = nullptr;
});
}
}
@@ -0,0 +1,99 @@
#ifndef NNTPCHAN_SERVER_HPP
#define NNTPCHAN_SERVER_HPP
#include <uv.h>
#include <deque>
#include <functional>
#include <string>
namespace nntpchan
{
class Server;
struct IConnHandler
{
virtual ~IConnHandler() {};
/** got inbound data */
virtual void OnData(const char * data, ssize_t s) = 0;
/** get next line of data to send */
std::string GetNextLine();
/** return true if we have a line to send */
bool HasNextLine();
/** return true if we should close this connection otherwise return false */
virtual bool ShouldClose() = 0;
/** queue a data send */
void QueueLine(const std::string & line);
virtual void Greet() = 0;
private:
std::deque<std::string> m_sendlines;
};
/** server connection handler interface */
struct IServerConn
{
IServerConn(uv_loop_t * l, uv_stream_t * s, Server * parent, IConnHandler * h);
virtual ~IServerConn();
virtual void Close();
virtual void Greet() = 0;
virtual void SendNextReply() = 0;
virtual bool IsTimedOut() = 0;
void SendString(const std::string & str);
Server * Parent() { return m_parent; };
IConnHandler * GetHandler() { return m_handler; };
uv_loop_t * GetLoop() { return m_loop; };
private:
uv_tcp_t m_conn;
uv_loop_t * m_loop;
Server * m_parent;
IConnHandler * m_handler;
char m_readbuff[65536];
};
class Server
{
public:
Server(uv_loop_t * loop);
/** called after socket close, NEVER call directly */
virtual ~Server() {}
/** create connection handler from open stream */
virtual IServerConn * CreateConn(uv_stream_t * s) = 0;
/** close all sockets and stop */
void Close();
/** bind to address */
void Bind(const std::string & addr);
typedef std::function<void(IServerConn *)> ConnVisitor;
/** visit all open connections */
void VisitConns(ConnVisitor v);
/** remove connection from server, called after proper close */
void RemoveConn(IServerConn * conn);
protected:
uv_loop_t * GetLoop() { return m_loop; }
virtual void OnAcceptError(int status) = 0;
private:
operator uv_handle_t * () { return (uv_handle_t*) &m_server; }
operator uv_tcp_t * () { return &m_server; }
operator uv_stream_t * () { return (uv_stream_t *) &m_server; }
void OnAccept(uv_stream_t * s, int status);
std::deque<IServerConn *> m_conns;
uv_tcp_t m_server;
uv_loop_t * m_loop;
};
}
#endif
@@ -0,0 +1,59 @@
#include "storage.hpp"
#include <errno.h>
#include <sys/stat.h>
#include <sstream>
namespace nntpchan
{
ArticleStorage::ArticleStorage()
{
}
ArticleStorage::ArticleStorage(const std::string & fpath) {
SetPath(fpath);
}
ArticleStorage::~ArticleStorage()
{
}
void ArticleStorage::SetPath(const std::string & fpath)
{
basedir = fpath;
// quiet fail
// TODO: check for errors
mkdir(basedir.c_str(), 0700);
}
bool ArticleStorage::Accept(const std::string& msgid)
{
if (!IsValidMessageID(msgid)) return false;
auto s = MessagePath(msgid);
FILE * f = fopen(s.c_str(), "r");
if ( f == nullptr) return errno == ENOENT;
fclose(f);
return false;
}
std::string ArticleStorage::MessagePath(const std::string & msgid)
{
return basedir + GetPathSep() + msgid;
}
std::fstream * ArticleStorage::OpenRead(const std::string & msgid)
{
return OpenMode(msgid, std::ios::in);
}
std::fstream * ArticleStorage::OpenWrite(const std::string & msgid)
{
return OpenMode(msgid, std::ios::out);
}
char ArticleStorage::GetPathSep()
{
return '/';
}
}
@@ -0,0 +1,55 @@
#ifndef NNTPCHAN_STORAGE_HPP
#define NNTPCHAN_STORAGE_HPP
#include <fstream>
#include <string>
#include "message.hpp"
namespace nntpchan
{
class ArticleStorage
{
public:
ArticleStorage();
ArticleStorage(const std::string & fpath);
~ArticleStorage();
void SetPath(const std::string & fpath);
std::fstream * OpenWrite(const std::string & msgid);
std::fstream * OpenRead(const std::string & msgid);
/**
return true if we should accept a new message give its message id
*/
bool Accept(const std::string & msgid);
private:
template<typename Mode>
std::fstream * OpenMode(const std::string & msgid, const Mode & m)
{
if(IsValidMessageID(msgid))
{
std::fstream * f = new std::fstream;
f->open(MessagePath(msgid), m);
if(f->is_open())
return f;
delete f;
return nullptr;
}
else
return nullptr;
};
std::string MessagePath(const std::string & msgid);
static char GetPathSep();
std::string basedir;
};
}
#endif
+13
View File
@@ -0,0 +1,13 @@
#include "exec_frontend.hpp"
#include <cassert>
#include <iostream>
int main(int , char * [])
{
nntpchan::Frontend * f = new nntpchan::ExecFrontend("./contrib/nntpchan.sh");
assert(f->AcceptsMessage("<test@server>"));
assert(f->AcceptsNewsgroup("overchan.test"));
std::cout << "all good" << std::endl;
}
@@ -0,0 +1,92 @@
#include "base64.hpp"
#include "crypto.hpp"
#include <cassert>
#include <cstring>
#include <string>
#include <iostream>
#include <sodium.h>
static void print_help(const std::string & exename)
{
std::cout << "usage: " << exename << " [help|gen|check]" << std::endl;
}
static void print_long_help()
{
}
static void gen_passwd(const std::string & username, const std::string & passwd)
{
std::array<uint8_t, 8> random;
randombytes_buf(random.data(), random.size());
std::string salt = nntpchan::B64Encode(random.data(), random.size());
std::string cred = passwd + salt;
nntpchan::SHA512Digest d;
nntpchan::SHA512((const uint8_t *)cred.c_str(), cred.size(), d);
std::string hash = nntpchan::B64Encode(d.data(), d.size());
std::cout << username << ":" << hash << ":" << salt << std::endl;
}
static bool check_cred(const std::string & cred, const std::string & passwd)
{
auto idx = cred.find(":");
if(idx == std::string::npos || idx == 0) return false;
std::string part = cred.substr(idx+1);
idx = part.find(":");
if(idx == std::string::npos || idx == 0) return false;
std::string salt = part.substr(idx+1);
std::string hash = part.substr(0, idx);
std::vector<uint8_t> h;
if(!nntpchan::B64Decode(hash, h)) return false;
nntpchan::SHA512Digest d;
std::string l = passwd + salt;
nntpchan::SHA512((const uint8_t*)l.data(), l.size(), d);
return std::memcmp(h.data(), d.data(), d.size()) == 0;
}
int main(int argc, char * argv[])
{
assert(sodium_init() == 0);
if(argc == 1) {
print_help(argv[0]);
return 1;
}
std::string cmd(argv[1]);
if (cmd == "help") {
print_long_help();
return 0;
}
if (cmd == "gen") {
if(argc == 4) {
gen_passwd(argv[2], argv[3]);
return 0;
} else {
std::cout << "usage: " << argv[0] << " gen username password" << std::endl;
return 1;
}
}
if(cmd == "check" ) {
std::string cred;
std::cout << "credential: " ;
if(!std::getline(std::cin, cred)) {
return 1;
}
std::string passwd;
std::cout << "password: ";
if(!std::getline(std::cin, passwd)) {
return 1;
}
if(check_cred(cred, passwd)) {
std::cout << "okay" << std::endl;
return 0;
}
std::cout << "bad login" << std::endl;
return 1;
}
print_help(argv[0]);
return 1;
}
@@ -0,0 +1,14 @@
#include "exec_frontend.hpp"
#include "message.hpp"
#include <cassert>
#include <iostream>
int main(int , char * [])
{
nntpchan::Frontend * f = new nntpchan::ExecFrontend("./contrib/nntpchan.sh");
assert(nntpchan::IsValidMessageID("<a28a71493831188@web.oniichan.onion>"));
assert(f->AcceptsNewsgroup("overchan.test"));
std::cout << "all good" << std::endl;
}
@@ -0,0 +1,8 @@
;; thanks stack overflow
;; https://stackoverflow.com/questions/4012321/how-can-i-access-the-path-to-the-current-directory-in-an-emacs-directory-variabl
((nil . ((eval . (set (make-local-variable 'my-project-path)
(file-name-directory
(let ((d (dir-locals-find-file ".")))
(if (stringp d) d (car d))))))
(eval . (setenv "GOPATH" my-project-path))
(eval . (message "Project directory set to `%s'." my-project-path)))))
+1
View File
@@ -0,0 +1 @@
nntpchand
+11
View File
@@ -0,0 +1,11 @@
REPO=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
all: clean build
build: nntpchand
nntpchand:
GOPATH=$(REPO) go build -v
clean:
GOPATH=$(REPO) go clean -v
@@ -0,0 +1,11 @@
<!doctype html>
<html>
<head>
<title> Error </title>
</head>
<body>
<pre> {{ .Error}} </pre>
</body>
</html>
@@ -0,0 +1,11 @@
<!doctype html>
<html>
<head>
<title> Overchan </title>
</head>
<body>
<pre>ebin</pre>
</body>
</html>
+9
View File
@@ -0,0 +1,9 @@
package main
import (
"nntpchan/cmd/nntpchan"
)
func main() {
nntpchan.Main()
}
@@ -0,0 +1,175 @@
package nntpchan
import (
log "github.com/Sirupsen/logrus"
"net"
_ "net/http/pprof"
"nntpchan/lib/config"
"nntpchan/lib/database"
"nntpchan/lib/frontend"
"nntpchan/lib/nntp"
"nntpchan/lib/store"
"nntpchan/lib/webhooks"
"os"
"os/signal"
"syscall"
"time"
)
type runStatus struct {
nntpListener net.Listener
run bool
done chan error
}
func (st *runStatus) Stop() {
st.run = false
if st.nntpListener != nil {
st.nntpListener.Close()
}
st.nntpListener = nil
log.Info("stopping daemon process")
}
func Main() {
st := &runStatus{
run: true,
done: make(chan error),
}
log.Info("starting up nntpchan...")
cfgFname := "nntpchan.json"
conf, err := config.Ensure(cfgFname)
if err != nil {
log.Fatal(err)
}
if conf.Log == "debug" {
log.SetLevel(log.DebugLevel)
}
sconfig := conf.Store
if sconfig == nil {
log.Fatal("no article storage configured")
}
nconfig := conf.NNTP
if nconfig == nil {
log.Fatal("no nntp server configured")
}
dconfig := conf.Database
if dconfig == nil {
log.Fatal("no database configured")
}
// create nntp server
nserv := nntp.NewServer()
nserv.Config = nconfig
nserv.Feeds = conf.Feeds
if nconfig.LoginsFile != "" {
nserv.Auth = nntp.FlatfileAuth(nconfig.LoginsFile)
}
// create article storage
nserv.Storage, err = store.NewFilesytemStorage(sconfig.Path, true)
if err != nil {
log.Fatal(err)
}
if conf.WebHooks != nil && len(conf.WebHooks) > 0 {
// put webhooks into nntp server event hooks
nserv.Hooks = webhooks.NewWebhooks(conf.WebHooks, nserv.Storage)
}
if conf.NNTPHooks != nil && len(conf.NNTPHooks) > 0 {
var hooks nntp.MulitHook
if nserv.Hooks != nil {
hooks = append(hooks, nserv.Hooks)
}
for _, h := range conf.NNTPHooks {
hooks = append(hooks, nntp.NewHook(h))
}
nserv.Hooks = hooks
}
var frontends []frontend.Frontend
var db database.Database
for _, fconf := range conf.Frontends {
var f frontend.Frontend
f, err = frontend.NewHTTPFrontend(&fconf, db, nserv.Storage)
if err == nil {
log.Infof("serving frontend %s", f.Name())
go f.Serve()
frontends = append(frontends, f)
} else {
log.Fatalf("failed to set up frontend %s: %s", fconf.Name(), err.Error())
}
}
// start persisting feeds
go nserv.PersistFeeds()
// handle signals
sigchnl := make(chan os.Signal, 1)
signal.Notify(sigchnl, syscall.SIGHUP, os.Interrupt)
go func() {
for {
s := <-sigchnl
if s == syscall.SIGHUP {
// handle SIGHUP
conf, err := config.Ensure(cfgFname)
if err == nil {
log.Infof("reloading config: %s", cfgFname)
nserv.ReloadServer(conf.NNTP)
nserv.ReloadFeeds(conf.Feeds)
nserv.ReloadStorage(conf.Store)
for idx := range frontends {
f := frontends[idx]
for i := range conf.Frontends {
c := conf.Frontends[i]
if c.Name() == f.Name() {
// TODO: inject storage config?
f.Reload(&c)
}
}
}
} else {
log.Errorf("failed to reload config: %s", err)
}
} else if s == os.Interrupt {
// handle interrupted, clean close
st.Stop()
return
}
}
}()
go func() {
var err error
for st.run {
var nl net.Listener
naddr := conf.NNTP.Bind
log.Infof("Bind nntp server to %s", naddr)
nl, err = net.Listen("tcp", naddr)
if err == nil {
st.nntpListener = nl
err = nserv.Serve(nl)
if err != nil {
nl.Close()
log.Errorf("nntpserver.serve() %s", err.Error())
}
} else {
log.Errorf("nntp server net.Listen failed: %s", err.Error())
}
time.Sleep(time.Second)
}
st.done <- err
}()
e := <-st.done
if e != nil {
log.Fatal(e)
}
log.Info("ended")
}
@@ -0,0 +1,42 @@
package main
// simple nntp server
import (
log "github.com/Sirupsen/logrus"
"github.com/majestrate/srndv2/lib/config"
"github.com/majestrate/srndv2/lib/nntp"
"github.com/majestrate/srndv2/lib/store"
"net"
)
func main() {
log.Info("starting NNTP server...")
conf, err := config.Ensure("settings.json")
if err != nil {
log.Fatal(err)
}
if conf.Log == "debug" {
log.SetLevel(log.DebugLevel)
}
serv := &nntp.Server{
Config: conf.NNTP,
Feeds: conf.Feeds,
}
serv.Storage, err = store.NewFilesytemStorage(conf.Store.Path, false)
if err != nil {
log.Fatal(err)
}
l, err := net.Listen("tcp", conf.NNTP.Bind)
if err != nil {
log.Fatal(err)
}
log.Info("listening on ", l.Addr())
err = serv.Serve(l)
if err != nil {
log.Fatal(err)
}
}
@@ -0,0 +1,4 @@
//
// server admin panel
//
package admin
@@ -0,0 +1,16 @@
package admin
import (
"net/http"
)
type Server struct {
}
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
func NewServer() *Server {
return &Server{}
}
@@ -0,0 +1,10 @@
package api
import (
"nntpchan/lib/model"
)
// json api
type API interface {
MakePost(p model.Post)
}
@@ -0,0 +1,2 @@
// json api
package api
@@ -0,0 +1,20 @@
package api
import (
"github.com/gorilla/mux"
"net/http"
)
// api server
type Server struct {
}
func (s *Server) HandlePing(w http.ResponseWriter, r *http.Request) {
}
// inject api routes
func (s *Server) SetupRoutes(r *mux.Router) {
// setup api pinger
r.Path("/ping").HandlerFunc(s.HandlePing)
}
@@ -0,0 +1,73 @@
package config
import "regexp"
// configration for local article policies
type ArticleConfig struct {
// explicitly allow these newsgroups (regexp)
AllowGroups []string `json:"whitelist"`
// explicitly disallow these newsgroups (regexp)
DisallowGroups []string `json:"blacklist"`
// only allow explicitly allowed groups
ForceWhitelist bool `json:"force-whitelist"`
// allow anonymous posts?
AllowAnon bool `json:"anon"`
// allow attachments?
AllowAttachments bool `json:"attachments"`
// allow anonymous attachments?
AllowAnonAttachments bool `json:"anon-attachments"`
}
func (c *ArticleConfig) AllowGroup(group string) bool {
for _, g := range c.DisallowGroups {
r := regexp.MustCompile(g)
if r.MatchString(group) && c.ForceWhitelist {
// disallowed
return false
}
}
// check allowed groups first
for _, g := range c.AllowGroups {
r := regexp.MustCompile(g)
if r.MatchString(g) {
return true
}
}
return !c.ForceWhitelist
}
// allow an article?
func (c *ArticleConfig) Allow(msgid, group string, anon, attachment bool) bool {
// check attachment policy
if c.AllowGroup(group) {
allow := true
// no anon ?
if anon && !c.AllowAnon {
allow = false
}
// no attachments ?
if allow && attachment && !c.AllowAttachments {
allow = false
}
// no anon attachments ?
if allow && attachment && anon && !c.AllowAnonAttachments {
allow = false
}
return allow
} else {
return false
}
}
var DefaultArticlePolicy = ArticleConfig{
AllowGroups: []string{"ctl", "overchan.test"},
DisallowGroups: []string{"overchan.cp"},
ForceWhitelist: false,
AllowAnon: true,
AllowAttachments: true,
AllowAnonAttachments: false,
}
@@ -0,0 +1,13 @@
package config
// caching interface configuration
type CacheConfig struct {
// backend cache driver name
Backend string `json:"backend"`
// address for cache
Addr string `json:"addr"`
// username for login
User string `json:"user"`
// password for login
Password string `json:"password"`
}
@@ -0,0 +1,87 @@
package config
import (
"bytes"
"encoding/json"
"io/ioutil"
"os"
)
// main configuration
type Config struct {
// nntp server configuration
NNTP *NNTPServerConfig `json:"nntp"`
// log level
Log string `json:"log"`
// article storage config
Store *StoreConfig `json:"storage"`
// web hooks to call
WebHooks []*WebhookConfig `json:"webhooks"`
// external scripts to call
NNTPHooks []*NNTPHookConfig `json:"nntphooks"`
// database backend configuration
Database *DatabaseConfig `json:"db"`
// list of feeds to add on runtime
Feeds []*FeedConfig `json:"feeds"`
// frontend config
Frontends []FrontendConfig `json:"frontends"`
// unexported fields ...
// absolute filepath to configuration
fpath string
}
// default configuration
var DefaultConfig = Config{
Store: &DefaultStoreConfig,
NNTP: &DefaultNNTPConfig,
Database: &DefaultDatabaseConfig,
WebHooks: []*WebhookConfig{DefaultWebHookConfig},
NNTPHooks: []*NNTPHookConfig{DefaultNNTPHookConfig},
Feeds: DefaultFeeds,
Frontends: []FrontendConfig{DefaultFrontendConfig},
Log: "debug",
}
// reload configuration
func (c *Config) Reload() (err error) {
var b []byte
b, err = ioutil.ReadFile(c.fpath)
if err == nil {
err = json.Unmarshal(b, c)
}
return
}
// ensure that a config file exists
// creates one if it does not exist
func Ensure(fname string) (cfg *Config, err error) {
_, err = os.Stat(fname)
if os.IsNotExist(err) {
err = nil
var d []byte
d, err = json.Marshal(&DefaultConfig)
if err == nil {
b := new(bytes.Buffer)
err = json.Indent(b, d, "", " ")
if err == nil {
err = ioutil.WriteFile(fname, b.Bytes(), 0600)
}
}
}
if err == nil {
cfg, err = Load(fname)
}
return
}
// load configuration file
func Load(fname string) (cfg *Config, err error) {
cfg = new(Config)
cfg.fpath = fname
err = cfg.Reload()
if err != nil {
cfg = nil
}
return
}
@@ -0,0 +1,18 @@
package config
type DatabaseConfig struct {
// url or address for database connector
Addr string `json:"addr"`
// password to use
Password string `json:"password"`
// username to use
Username string `json:"username"`
// type of database to use
Type string `json:"type"`
}
var DefaultDatabaseConfig = DatabaseConfig{
Type: "postgres",
Addr: "/var/run/postgresql",
Password: "",
}
@@ -0,0 +1,4 @@
//
// package for parsing config files
//
package config
@@ -0,0 +1,33 @@
package config
// configuration for 1 nntp feed
type FeedConfig struct {
// feed's policy, filters articles
Policy *ArticleConfig `json:"policy"`
// remote server's address
Addr string `json:"addr"`
// proxy server config
Proxy *ProxyConfig `json:"proxy"`
// nntp username to log in with
Username string `json:"username"`
// nntp password to use when logging in
Password string `json:"password"`
// do we want to use tls?
TLS bool `json:"tls"`
// the name of this feed
Name string `json:"name"`
// how often to pull articles from the server in minutes
// 0 for never
PullInterval int `json:"pull"`
}
var DuummyFeed = FeedConfig{
Policy: &DefaultArticlePolicy,
Addr: "nntp.dummy.tld:1119",
Proxy: &DefaultTorProxy,
Name: "dummy",
}
var DefaultFeeds = []*FeedConfig{
&DuummyFeed,
}
@@ -0,0 +1,31 @@
package config
import (
"fmt"
)
type FrontendConfig struct {
// bind to address
BindAddr string `json:"bind"`
// frontend cache
Cache *CacheConfig `json:"cache"`
// frontend ssl settings
SSL *SSLSettings `json:"ssl"`
// static files directory
Static string `json:"static_dir"`
// http middleware configuration
Middleware *MiddlewareConfig `json:"middleware"`
// storage config
Storage *StoreConfig `json:"-"`
}
func (cfg *FrontendConfig) Name() string {
return fmt.Sprintf("frontend-%s", cfg.BindAddr)
}
// default Frontend Configuration
var DefaultFrontendConfig = FrontendConfig{
BindAddr: "127.0.0.1:18888",
Static: "./files/static/",
Middleware: &DefaultMiddlewareConfig,
}
@@ -0,0 +1,15 @@
package config
// config for external callback for nntp articles
type NNTPHookConfig struct {
// name of hook
Name string `json:"name"`
// executable script path to be called with arguments: /path/to/article
Exec string `json:"exec"`
}
// default dummy hook
var DefaultNNTPHookConfig = &NNTPHookConfig{
Name: "dummy",
Exec: "/bin/true",
}
@@ -0,0 +1,14 @@
package config
// configuration for http middleware
type MiddlewareConfig struct {
// middleware type, currently just 1 is available: overchan
Type string `json:"type"`
// directory for our html templates
Templates string `json:"templates_dir"`
}
var DefaultMiddlewareConfig = MiddlewareConfig{
Type: "overchan",
Templates: "./files/templates/overchan/",
}
@@ -0,0 +1,24 @@
package config
type NNTPServerConfig struct {
// address to bind to
Bind string `json:"bind"`
// name of the nntp server
Name string `json:"name"`
// default inbound article policy
Article *ArticleConfig `json:"policy"`
// do we allow anonymous NNTP sync?
AnonNNTP bool `json:"anon-nntp"`
// ssl settings for nntp
SSL *SSLSettings
// file with login credentials
LoginsFile string `json:"authfile"`
}
var DefaultNNTPConfig = NNTPServerConfig{
AnonNNTP: false,
Bind: "0.0.0.0:1119",
Name: "nntp.server.tld",
Article: &DefaultArticlePolicy,
LoginsFile: "",
}
@@ -0,0 +1,13 @@
package config
// proxy configuration
type ProxyConfig struct {
Type string `json:"type"`
Addr string `json:"addr"`
}
// default tor proxy
var DefaultTorProxy = ProxyConfig{
Type: "socks",
Addr: "127.0.0.1:9050",
}
@@ -0,0 +1,11 @@
package config
// settings for setting up ssl
type SSLSettings struct {
// path to ssl private key
SSLKeyFile string `json:"key"`
// path to ssl certificate signed by CA
SSLCertFile string `json:"cert"`
// domain name to use for ssl
DomainName string `json:"fqdn"`
}
@@ -0,0 +1,10 @@
package config
type StoreConfig struct {
// path to article directory
Path string `json:"path"`
}
var DefaultStoreConfig = StoreConfig{
Path: "storage",
}
@@ -0,0 +1,17 @@
package config
// configuration for a single web hook
type WebhookConfig struct {
// user provided name for this hook
Name string `json:"name"`
// callback URL for webhook
URL string `json:"url"`
// dialect to use when calling webhook
Dialect string `json:"dialect"`
}
var DefaultWebHookConfig = &WebhookConfig{
Name: "vichan",
Dialect: "vichan",
URL: "http://localhost/webhook.php",
}
@@ -0,0 +1,5 @@
//
// nntpchan crypto package
// wraps all external crypro libs
//
package crypto
@@ -0,0 +1,8 @@
package crypto
import (
"github.com/dchest/blake256"
)
// common hash function is blake2
var Hash = blake256.New
@@ -0,0 +1,77 @@
package crypto
import (
"crypto/sha512"
"hash"
"nntpchan/lib/crypto/nacl"
)
type fuckyNacl struct {
k []byte
hash hash.Hash
}
func (fucky *fuckyNacl) Write(d []byte) (int, error) {
return fucky.hash.Write(d)
}
func (fucky *fuckyNacl) Sign() (s Signature) {
h := fucky.hash.Sum(nil)
if h == nil {
panic("fuck.hash.Sum == nil")
}
_, sec := nacl.SeedToKeyPair(fucky.k)
sig := nacl.CryptoSignFucky(h, sec)
if sig == nil {
panic("fucky signer's call to nacl.CryptoSignFucky returned nil")
}
s = Signature(sig)
fucky.resetState()
return
}
// reset inner state so we can reuse this fuckyNacl for another operation
func (fucky *fuckyNacl) resetState() {
fucky.hash = sha512.New()
}
func (fucky *fuckyNacl) Verify(sig Signature) (valid bool) {
h := fucky.hash.Sum(nil)
if h == nil {
panic("fucky.hash.Sum == nil")
}
valid = nacl.CryptoVerifyFucky(h, sig, fucky.k)
fucky.resetState()
return
}
func createFucky(k []byte) *fuckyNacl {
return &fuckyNacl{
k: k,
hash: sha512.New(),
}
}
// create a standard signer given a secret key
func CreateSigner(sk []byte) Signer {
return createFucky(sk)
}
// create a standard verifier given a public key
func CreateVerifier(pk []byte) Verifer {
return createFucky(pk)
}
// get the public component given the secret key
func ToPublic(sk []byte) (pk []byte) {
pk, _ = nacl.SeedToKeyPair(sk)
return
}
// create a standard keypair
func GenKeypair() (pk, sk []byte) {
sk = RandBytes(32)
pk, _ = nacl.SeedToKeyPair(sk)
return
}
@@ -0,0 +1,44 @@
package nacl
import (
"crypto/sha512"
"edwards25519"
"golang.org/x/crypto/ed25519"
)
func CryptoVerifyFucky(h, sig, pk []byte) bool {
pub := make(ed25519.PublicKey, ed25519.PublicKeySize)
copy(pub, pk)
return ed25519.Verify(pub, h, sig)
}
func CryptoSignFucky(hash, sk []byte) []byte {
sec := make(ed25519.PrivateKey, ed25519.PrivateKeySize)
copy(sec, sk)
return ed25519.Sign(sec, hash)
}
func SeedToKeyPair(seed []byte) (pk, sk []byte) {
h := sha512.Sum512(seed[0:32])
sk = h[:]
sk[0] &= 248
sk[31] &= 63
sk[31] |= 64
// scalarmult magick shit
pk = scalarBaseMult(sk[0:32])
copy(sk[0:32], seed[0:32])
copy(sk[32:64], pk[0:32])
return
}
func scalarBaseMult(sk []byte) (pk []byte) {
var skey [32]byte
var pkey [32]byte
copy(skey[:], sk[0:32])
var h edwards25519.ExtendedGroupElement
edwards25519.GeScalarMultBase(&h, &skey)
h.ToBytes(&pkey)
pk = pkey[:]
return
}
@@ -0,0 +1,34 @@
package crypto
import (
"bytes"
"crypto/rand"
"io"
"testing"
)
func TestNaclToPublic(t *testing.T) {
pk, sk := GenKeypair()
t_pk := ToPublic(sk)
if !bytes.Equal(pk, t_pk) {
t.Logf("%q != %q", pk, t_pk)
t.Fail()
}
}
func TestNaclSignVerify(t *testing.T) {
var msg [1024]byte
pk, sk := GenKeypair()
io.ReadFull(rand.Reader, msg[:])
signer := CreateSigner(sk)
signer.Write(msg[:])
sig := signer.Sign()
verifier := CreateVerifier(pk)
verifier.Write(msg[:])
if !verifier.Verify(sig) {
t.Logf("%q is invalid signature and is %dB long", sig, len(sig))
t.Fail()
}
}
@@ -0,0 +1,13 @@
package crypto
import (
"crypto/rand"
"io"
)
// generate random bytes
func RandBytes(n int) []byte {
b := make([]byte, n)
io.ReadFull(rand.Reader, b)
return b
}
@@ -0,0 +1,25 @@
package crypto
import "io"
// a detached signature
type Signature []byte
type SigEncoder interface {
// encode a signature to an io.Writer
// return error if one occurrened while writing out signature
Encode(sig Signature, w io.Writer) error
// encode a signature to a string
EncodeString(sig Signature) string
}
// a decoder of signatures
type SigDecoder interface {
// decode signature from io.Reader
// reads all data until io.EOF
// returns singaure or error if an error occured while reading
Decode(r io.Reader) (Signature, error)
// decode a signature from string
// returns signature or error if an error ocurred while decoding
DecodeString(str string) (Signature, error)
}
@@ -0,0 +1,14 @@
package crypto
import "io"
//
// provides generic signing interface for producing detached signatures
// call Write() to feed data to be signed, call Sign() to generate
// a detached signature
//
type Signer interface {
io.Writer
// generate detached Signature from previously fed body via Write()
Sign() Signature
}
@@ -0,0 +1,14 @@
package crypto
import "io"
// provides generic signature
// call Write() to feed in message body
// once the entire body has been fed in via Write() call Verify() with detached
// signature to verify the detached signature against the previously fed body
type Verifer interface {
io.Writer
// verify detached signature from body previously fed via Write()
// return true if the detached signature is valid given the body
Verify(sig Signature) bool
}
@@ -0,0 +1,29 @@
package database
import (
"errors"
"nntpchan/lib/config"
"nntpchan/lib/model"
"strings"
)
//
type Database interface {
ThreadByMessageID(msgid string) (*model.Thread, error)
ThreadByHash(hash string) (*model.Thread, error)
MessageIDByHash(hash string) (string, error)
BoardPage(newsgroup string, pageno, perpage int) (*model.BoardPage, error)
StorePost(post model.Post) error
Init() error
}
// get new database connector from configuration
func NewDBFromConfig(c *config.DatabaseConfig) (db Database, err error) {
dbtype := strings.ToLower(c.Type)
if dbtype == "postgres" {
db, err = createPostgresDatabase(c.Addr, c.Username, c.Password)
} else {
err = errors.New("no such database driver: " + c.Type)
}
return
}
@@ -0,0 +1,4 @@
//
// database driver
//
package database
@@ -0,0 +1,58 @@
package database
import (
"database/sql"
_ "github.com/lib/pq"
"nntpchan/lib/model"
)
type PostgresDB struct {
conn *sql.DB
}
func (db *PostgresDB) ThreadByMessageID(msgid string) (thread *model.Thread, err error) {
return
}
func (db *PostgresDB) ThreadByHash(hash string) (thread *model.Thread, err error) {
return
}
func (db *PostgresDB) MessageIDByHash(hash string) (msgid string, err error) {
return
}
func (db *PostgresDB) BoardPage(newsgroup string, pageno, perpage int) (page *model.BoardPage, err error) {
return
}
func (db *PostgresDB) StorePost(post model.Post) (err error) {
return
}
func (db *PostgresDB) Init() (err error) {
return
}
func createPostgresDatabase(addr, user, passwd string) (p *PostgresDB, err error) {
p = new(PostgresDB)
var authstring string
if len(addr) > 0 {
authstring += " host=" + addr
}
if len(user) > 0 {
authstring += " username=" + user
}
if len(passwd) > 0 {
authstring += " password=" + passwd
}
p.conn, err = sql.Open("postgres", authstring)
if err != nil {
p = nil
}
return
}
@@ -0,0 +1,123 @@
package frontend
import (
"encoding/json"
"errors"
"fmt"
"github.com/dchest/captcha"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
"net/http"
"nntpchan/lib/config"
)
// server of captchas
// implements frontend.Middleware
type CaptchaServer struct {
h int
w int
store *sessions.CookieStore
prefix string
sessionName string
}
// create new captcha server using existing session store
func NewCaptchaServer(w, h int, prefix string, store *sessions.CookieStore) *CaptchaServer {
return &CaptchaServer{
h: h,
w: w,
prefix: prefix,
store: store,
sessionName: "captcha",
}
}
func (cs *CaptchaServer) Reload(c *config.MiddlewareConfig) {
}
func (cs *CaptchaServer) SetupRoutes(m *mux.Router) {
m.Path("/new").HandlerFunc(cs.NewCaptcha)
m.Path("/img/{f}").Handler(captcha.Server(cs.w, cs.h))
m.Path("/verify.json").HandlerFunc(cs.VerifyCaptcha)
}
// return true if this session has solved the last captcha given provided solution, otherwise false
func (cs *CaptchaServer) CheckSession(w http.ResponseWriter, r *http.Request, solution string) (bool, error) {
s, err := cs.store.Get(r, cs.sessionName)
if err == nil {
id, ok := s.Values["captcha_id"]
if ok {
return captcha.VerifyString(id.(string), solution), nil
}
}
return false, err
}
// verify a captcha
func (cs *CaptchaServer) VerifyCaptcha(w http.ResponseWriter, r *http.Request) {
dec := json.NewDecoder(r.Body)
defer r.Body.Close()
// request
req := make(map[string]string)
// response
resp := make(map[string]interface{})
resp["solved"] = false
// decode request
err := dec.Decode(req)
if err == nil {
// decode okay
id, ok := req["id"]
if ok {
// we have id
solution, ok := req["solution"]
if ok {
// we have solution and id
resp["solved"] = captcha.VerifyString(id, solution)
} else {
// we don't have solution
err = errors.New("no captcha solution provided")
}
} else {
// we don't have id
err = errors.New("no captcha id provided")
}
}
if err != nil {
// error happened
resp["error"] = err.Error()
}
// send reply
w.Header().Set("Content-Type", "text/json; encoding=UTF-8")
enc := json.NewEncoder(w)
enc.Encode(resp)
}
// generate a new captcha
func (cs *CaptchaServer) NewCaptcha(w http.ResponseWriter, r *http.Request) {
// obtain session
sess, err := cs.store.Get(r, cs.sessionName)
if err != nil {
// failed to obtain session
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// new captcha
id := captcha.New()
// do we want to interpret as json?
use_json := r.URL.Query().Get("t") == "json"
// image url
url := fmt.Sprintf("%simg/%s.png", cs.prefix, id)
if use_json {
// send json
enc := json.NewEncoder(w)
enc.Encode(map[string]string{"id": id, "url": url})
} else {
// set captcha id
sess.Values["captcha_id"] = id
// save session
sess.Save(r, w)
// rediect to image
http.Redirect(w, r, url, http.StatusFound)
}
}
@@ -0,0 +1,5 @@
//
// nntpchan frontend
// allows posting to nntpchan network via various implementations
//
package frontend
@@ -0,0 +1,50 @@
package frontend
import (
"nntpchan/lib/config"
"nntpchan/lib/database"
"nntpchan/lib/model"
"nntpchan/lib/nntp"
"nntpchan/lib/store"
)
// a frontend that displays nntp posts and allows posting
type Frontend interface {
// run mainloop
Serve()
// do we accept this inbound post?
AllowPost(p model.PostReference) bool
// trigger a manual regen of indexes for a root post
Regen(p model.PostReference)
// implements nntp.EventHooks
GotArticle(msgid nntp.MessageID, group nntp.Newsgroup)
// implements nntp.EventHooks
SentArticleVia(msgid nntp.MessageID, feedname string)
// reload config
Reload(c *config.FrontendConfig)
// get frontend name
Name() string
}
// create a new http frontend give frontend config
func NewHTTPFrontend(c *config.FrontendConfig, db database.Database, s store.Storage) (f Frontend, err error) {
var mid Middleware
if c.Middleware != nil {
// middleware configured
mid, err = OverchanMiddleware(c.Middleware, db)
}
if err == nil {
// create http frontend only if no previous errors
f, err = createHttpFrontend(c, mid, db, s)
}
return
}
@@ -0,0 +1,147 @@
package frontend
import (
"fmt"
log "github.com/Sirupsen/logrus"
"github.com/gorilla/mux"
"net/http"
"nntpchan/lib/admin"
"nntpchan/lib/api"
"nntpchan/lib/config"
"nntpchan/lib/database"
"nntpchan/lib/model"
"nntpchan/lib/nntp"
"nntpchan/lib/store"
"time"
)
// http frontend server
// provides glue layer between nntp and middleware
type httpFrontend struct {
// bind address
addr string
// http mux
httpmux *mux.Router
// admin panel
adminPanel *admin.Server
// static files path
staticDir string
// http middleware
middleware Middleware
// api server
apiserve *api.Server
// database driver
db database.Database
// article storage
storage store.Storage
}
func (f *httpFrontend) Name() string {
return fmt.Sprintf("frontend-%s", f.addr)
}
// reload http frontend
// reloads middleware
func (f *httpFrontend) Reload(c *config.FrontendConfig) {
if f.middleware == nil {
if c.Middleware != nil {
var err error
// no middleware set, create middleware
f.middleware, err = OverchanMiddleware(c.Middleware, f.db)
if err != nil {
log.Errorf("overchan middleware reload failed: %s", err.Error())
}
}
} else {
// middleware exists
// do middleware reload
f.middleware.Reload(c.Middleware)
}
}
// serve http requests from net.Listener
func (f *httpFrontend) Serve() {
// serve http
for {
err := http.ListenAndServe(f.addr, f.httpmux)
if err != nil {
log.Errorf("failed to listen and serve with frontend: %s", err)
}
time.Sleep(time.Second)
}
}
// serve robots.txt page
func (f *httpFrontend) serveRobots(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "User-Agent: *\nDisallow: /\n")
}
func (f *httpFrontend) AllowPost(p model.PostReference) bool {
// TODO: implement
return true
}
func (f *httpFrontend) Regen(p model.PostReference) {
// TODO: implement
}
func (f *httpFrontend) GotArticle(msgid nntp.MessageID, group nntp.Newsgroup) {
// TODO: implement
}
func (f *httpFrontend) SentArticleVia(msgid nntp.MessageID, feedname string) {
// TODO: implement
}
func createHttpFrontend(c *config.FrontendConfig, mid Middleware, db database.Database, s store.Storage) (f *httpFrontend, err error) {
f = new(httpFrontend)
// set db
// db.Ensure() called elsewhere
f.db = db
// set up storage
// s.Ensure() called elsewhere
f.storage = s
// set bind address
f.addr = c.BindAddr
// set up mux
f.httpmux = mux.NewRouter()
// set up admin panel
f.adminPanel = admin.NewServer()
// set static files dir
f.staticDir = c.Static
// set middleware
f.middleware = mid
// set up routes
if f.adminPanel != nil {
// route up admin panel
f.httpmux.PathPrefix("/admin/").Handler(f.adminPanel)
}
if f.middleware != nil {
// route up middleware
f.middleware.SetupRoutes(f.httpmux)
}
if f.apiserve != nil {
// route up api
f.apiserve.SetupRoutes(f.httpmux.PathPrefix("/api/").Subrouter())
}
// route up robots.txt
f.httpmux.Path("/robots.txt").HandlerFunc(f.serveRobots)
// route up static files
f.httpmux.PathPrefix("/static/").Handler(http.FileServer(http.Dir(f.staticDir)))
return
}
@@ -0,0 +1,14 @@
package frontend
import (
"github.com/gorilla/mux"
"nntpchan/lib/config"
)
// http middleware
type Middleware interface {
// set up routes
SetupRoutes(m *mux.Router)
// reload with new configuration
Reload(c *config.MiddlewareConfig)
}
@@ -0,0 +1,115 @@
package frontend
import (
log "github.com/Sirupsen/logrus"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
"html/template"
"net/http"
"nntpchan/lib/config"
"nntpchan/lib/database"
"path/filepath"
"strconv"
)
// standard overchan imageboard middleware
type overchanMiddleware struct {
templ *template.Template
captcha *CaptchaServer
store *sessions.CookieStore
db database.Database
}
func (m *overchanMiddleware) SetupRoutes(mux *mux.Router) {
// setup front page handler
mux.Path("/").HandlerFunc(m.ServeIndex)
// setup thread handler
mux.Path("/t/{id}/").HandlerFunc(m.ServeThread)
// setup board page handler
mux.Path("/b/{name}/").HandlerFunc(m.ServeBoardPage)
// setup posting endpoint
mux.Path("/post")
// create captcha
captchaPrefix := "/captcha/"
m.captcha = NewCaptchaServer(200, 400, captchaPrefix, m.store)
// setup captcha endpoint
m.captcha.SetupRoutes(mux.PathPrefix(captchaPrefix).Subrouter())
}
// reload middleware
func (m *overchanMiddleware) Reload(c *config.MiddlewareConfig) {
// reload templates
templ, err := template.ParseGlob(filepath.Join(c.Templates, "*.tmpl"))
if err == nil {
log.Infof("middleware reloaded templates")
m.templ = templ
} else {
log.Errorf("middleware reload failed: %s", err.Error())
}
}
func (m *overchanMiddleware) ServeBoardPage(w http.ResponseWriter, r *http.Request) {
param := mux.Vars(r)
board := param["name"]
page := r.URL.Query().Get("q")
pageno, err := strconv.Atoi(page)
if err == nil {
var obj interface{}
obj, err = m.db.BoardPage(board, pageno, 10)
if err == nil {
m.serveTemplate(w, r, "board.html.tmpl", obj)
} else {
m.serveTemplate(w, r, "error.html.tmpl", err)
}
} else {
// 404
http.NotFound(w, r)
}
}
// serve cached thread
func (m *overchanMiddleware) ServeThread(w http.ResponseWriter, r *http.Request) {
param := mux.Vars(r)
obj, err := m.db.ThreadByHash(param["id"])
if err == nil {
m.serveTemplate(w, r, "thread.html.tmpl", obj)
} else {
m.serveTemplate(w, r, "error.html.tmpl", err)
}
}
// serve index page
func (m *overchanMiddleware) ServeIndex(w http.ResponseWriter, r *http.Request) {
m.serveTemplate(w, r, "index.html.tmpl", nil)
}
// serve a template
func (m *overchanMiddleware) serveTemplate(w http.ResponseWriter, r *http.Request, tname string, obj interface{}) {
t := m.templ.Lookup(tname)
if t == nil {
log.WithFields(log.Fields{
"template": tname,
}).Warning("template not found")
http.NotFound(w, r)
} else {
err := t.Execute(w, obj)
if err != nil {
// error getting model
log.WithFields(log.Fields{
"error": err,
"template": tname,
}).Warning("failed to render template")
}
}
}
// create standard overchan middleware
func OverchanMiddleware(c *config.MiddlewareConfig, db database.Database) (m Middleware, err error) {
om := new(overchanMiddleware)
om.templ, err = template.ParseGlob(filepath.Join(c.Templates, "*.tmpl"))
om.db = db
if err == nil {
m = om
}
return
}
@@ -0,0 +1 @@
package frontend
@@ -0,0 +1 @@
package frontend
@@ -0,0 +1,15 @@
package model
type Article struct {
Subject string
Name string
Header map[string][]string
Text string
Attachments []Attachment
MessageID string
Newsgroup string
Reference string
Path string
Posted int64
Addr string
}
@@ -0,0 +1,10 @@
package model
type Attachment struct {
Path string
Name string
Mime string
Hash string
// only filled for api
Body string
}
@@ -0,0 +1,4 @@
package model
type Board struct {
}
@@ -0,0 +1,8 @@
package model
type BoardPage struct {
Name string
Page int
Pages int
Threads []Thread
}
@@ -0,0 +1,2 @@
// MVC models
package model
@@ -0,0 +1,29 @@
package model
import (
"time"
)
type ArticleHeader map[string][]string
// a ( MessageID , newsgroup ) tuple
type ArticleEntry [2]string
func (self ArticleEntry) Newsgroup() string {
return self[1]
}
func (self ArticleEntry) MessageID() string {
return self[0]
}
// a ( time point, post count ) tuple
type PostEntry [2]int64
func (self PostEntry) Time() time.Time {
return time.Unix(self[0], 0)
}
func (self PostEntry) Count() int64 {
return self[1]
}

Some files were not shown because too many files have changed in this diff Show More