Archived
1
0

Merge branch 'master' of ssh://github.com/majestrate/nntpchan

This commit is contained in:
Jeff 2017-08-12 18:20:13 -04:00
commit 1e69493eef
9 changed files with 77 additions and 6 deletions

View File

@ -5,18 +5,45 @@
package srnd package srnd
import ( import (
"bufio"
"bytes"
"encoding/base32" "encoding/base32"
"fmt" "fmt"
"github.com/majestrate/configparser" "github.com/majestrate/configparser"
"github.com/majestrate/nacl" "github.com/majestrate/nacl"
"io/ioutil"
"log" "log"
"net" "net"
"os" "os"
"path/filepath" "path/filepath"
"regexp"
"strings" "strings"
"time" "time"
) )
type FilterConfig struct {
globalFilters []*regexp.Regexp
}
func (fc *FilterConfig) LoadFile(fname string) (err error) {
var data []byte
data, err = ioutil.ReadFile(fname)
if err == nil {
r := bytes.NewReader(data)
sc := bufio.NewScanner(r)
for sc.Scan() {
txt := sc.Text()
idx := strings.Index(txt, "#")
if idx >= 0 {
txt = txt[:idx]
}
fc.globalFilters = append(fc.globalFilters, regexp.MustCompile(txt))
}
}
return
}
type FeedConfig struct { type FeedConfig struct {
policy FeedPolicy policy FeedPolicy
quarks map[string]string quarks map[string]string
@ -70,6 +97,7 @@ type SRNdConfig struct {
pprof *ProfilingConfig pprof *ProfilingConfig
hooks []*HookConfig hooks []*HookConfig
inboundPolicy *FeedPolicy inboundPolicy *FeedPolicy
filter FilterConfig
} }
// check for config files // check for config files
@ -417,6 +445,15 @@ func ReadConfig() *SRNdConfig {
} }
} }
filterFile := "filters.txt"
if CheckFile(filterFile) {
err = sconf.filter.LoadFile(filterFile)
if err != nil {
log.Fatalf("failed to load %s: %s", filterFile, err)
}
log.Printf("loaded %d filters", len(sconf.filter.globalFilters))
}
return &sconf return &sconf
} }

View File

@ -131,6 +131,16 @@ type NNTPDaemon struct {
article_lifetime time.Duration article_lifetime time.Duration
} }
// return true if text passes all checks and is okay for posting
func (self *NNTPDaemon) CheckText(text string) bool {
for _, re := range self.conf.filter.globalFilters {
if re.MatchString(text) {
return false
}
}
return true
}
func (self NNTPDaemon) End() { func (self NNTPDaemon) End() {
if self.listener != nil { if self.listener != nil {
self.listener.Close() self.listener.Close()
@ -478,6 +488,12 @@ func (self *NNTPDaemon) syncPull(proxy_type, proxy_addr, remote_addr string) {
} }
} }
func (self *NNTPDaemon) ExpireAll() {
log.Println("expiring all orphans")
self.expire = createExpirationCore(self.database, self.store, self.informHooks)
self.expire.ExpireOrphans()
}
// run daemon // run daemon
func (self *NNTPDaemon) Run() { func (self *NNTPDaemon) Run() {

View File

@ -77,6 +77,7 @@ func (self expire) ExpireThread(group, rootMsgid string) {
} }
} }
self.database.DeleteThread(rootMsgid) self.database.DeleteThread(rootMsgid)
self.database.DeleteArticle(rootMsgid)
self.expireCache(group, rootMsgid, rootMsgid) self.expireCache(group, rootMsgid, rootMsgid)
} }

View File

@ -393,7 +393,7 @@ func (self *httpFrontend) poll() {
R: msg.Body, R: msg.Body,
N: self.daemon.messageSizeLimitFor(nntp.Newsgroup()), N: self.daemon.messageSizeLimitFor(nntp.Newsgroup()),
} }
err = self.daemon.store.ProcessMessageBody(f, textproto.MIMEHeader(msg.Header), body) err = self.daemon.store.ProcessMessageBody(f, textproto.MIMEHeader(msg.Header), body, self.daemon.CheckText)
} }
} }
} }
@ -803,6 +803,11 @@ func (self *httpFrontend) handle_postRequest(pr *postRequest, b bannedFunc, e er
return return
} }
if !self.daemon.CheckText(pr.Message) {
e(errors.New("spam"))
return
}
if len(pr.Frontend) == 0 { if len(pr.Frontend) == 0 {
// :-DDD // :-DDD
pr.Frontend = "mongo.db.is.web.scale" pr.Frontend = "mongo.db.is.web.scale"

View File

@ -565,7 +565,7 @@ func (self *nntpConnection) storeMessage(daemon *NNTPDaemon, hdr textproto.MIMEH
// now store attachments and article // now store attachments and article
err = writeMIMEHeader(f, hdr) err = writeMIMEHeader(f, hdr)
if err == nil { if err == nil {
err = daemon.store.ProcessMessageBody(f, hdr, body) err = daemon.store.ProcessMessageBody(f, hdr, body, daemon.CheckText)
if err == nil { if err == nil {
// tell daemon // tell daemon
daemon.loadFromInfeed(msgid) daemon.loadFromInfeed(msgid)

View File

@ -65,7 +65,7 @@ type ArticleStore interface {
// process body of nntp message, register attachments and the article // process body of nntp message, register attachments and the article
// write the body into writer as we go through the body // write the body into writer as we go through the body
// does NOT write mime header // does NOT write mime header
ProcessMessageBody(wr io.Writer, hdr textproto.MIMEHeader, body *io.LimitedReader) error ProcessMessageBody(wr io.Writer, hdr textproto.MIMEHeader, body *io.LimitedReader, spamfilter func(string) bool) error
// register this post with the daemon // register this post with the daemon
RegisterPost(nntp NNTPMessage) error RegisterPost(nntp NNTPMessage) error
// register signed message // register signed message
@ -428,7 +428,9 @@ func (self *articleStore) getMIMEHeader(messageID string) (hdr textproto.MIMEHea
var msg *mail.Message var msg *mail.Message
msg, err = readMIMEHeader(r) msg, err = readMIMEHeader(r)
f.Close() f.Close()
hdr = textproto.MIMEHeader(msg.Header) if msg != nil {
hdr = textproto.MIMEHeader(msg.Header)
}
} }
if err != nil { if err != nil {
log.Println("failed to load article headers for", messageID, err) log.Println("failed to load article headers for", messageID, err)
@ -437,8 +439,12 @@ func (self *articleStore) getMIMEHeader(messageID string) (hdr textproto.MIMEHea
return hdr return hdr
} }
func (self *articleStore) ProcessMessageBody(wr io.Writer, hdr textproto.MIMEHeader, body *io.LimitedReader) (err error) { func (self *articleStore) ProcessMessageBody(wr io.Writer, hdr textproto.MIMEHeader, body *io.LimitedReader, spamfilter func(string) bool) (err error) {
err = read_message_body(body, hdr, self, wr, false, func(nntp NNTPMessage) { err = read_message_body(body, hdr, self, wr, false, func(nntp NNTPMessage) {
if !spamfilter(nntp.Message()) {
err = errors.New("spam message")
return
}
err = self.RegisterPost(nntp) err = self.RegisterPost(nntp)
if err == nil { if err == nil {
pk := hdr.Get("X-PubKey-Ed25519") pk := hdr.Get("X-PubKey-Ed25519")

View File

@ -66,6 +66,8 @@ func (self *VarnishCache) invalidateUkko() {
self.invalidate(fmt.Sprintf("%s%so/", self.varnish_url, self.prefix)) self.invalidate(fmt.Sprintf("%s%so/", self.varnish_url, self.prefix))
// TODO: this is lazy af // TODO: this is lazy af
self.RegenFrontPage() self.RegenFrontPage()
// TODO: this is also lazy af
self.invalidate(fmt.Sprintf("%s%shistory.html", self.varnish_url, self.prefix))
} }
func (self *VarnishCache) pollRegen() { func (self *VarnishCache) pollRegen() {

View File

@ -94,6 +94,9 @@ func main() {
} else { } else {
fmt.Fprintf(os.Stdout, "usage: %s tool mod [[add|del] pubkey]|[do modactiongoeshere]\n", os.Args[0]) fmt.Fprintf(os.Stdout, "usage: %s tool mod [[add|del] pubkey]|[do modactiongoeshere]\n", os.Args[0])
} }
} else if tool == "expire" {
daemon.Setup()
daemon.ExpireAll()
} else if tool == "rethumb" { } else if tool == "rethumb" {
if len(os.Args) >= 4 { if len(os.Args) >= 4 {
threads := runtime.NumCPU() threads := runtime.NumCPU()

View File

@ -8,7 +8,8 @@ template parameters:
<html> <html>
<head> <head>
<meta charset="utf-8"></meta> <meta charset="utf-8"></meta>
<link rel="stylesheet" href="{{prefix}}static/site.css" /> <!-- <link rel="stylesheet" href="{{prefix}}static/site.css" /> -->
<link rel="stylesheet" href="{{prefix}}static/krane.css" />
<link rel="stylesheet" href="{{prefix}}static/user.css" /> <link rel="stylesheet" href="{{prefix}}static/user.css" />
<title>{{#i18n.Translations}}{{post_history_title}}{{/i18n.Translations}}</title> <title>{{#i18n.Translations}}{{post_history_title}}{{/i18n.Translations}}</title>
</head> </head>