102 lines
2.3 KiB
Go
102 lines
2.3 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"net/http"
|
||
|
"net/url"
|
||
|
"os"
|
||
|
"regexp"
|
||
|
"strings"
|
||
|
"sync"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
long = regexp.MustCompile(`(.{72}\S*)\s+`)
|
||
|
file, requests *os.File
|
||
|
m sync.Mutex
|
||
|
)
|
||
|
|
||
|
func wrap(s string) string {
|
||
|
return strings.ReplaceAll(long.ReplaceAllString(
|
||
|
strings.ReplaceAll(s, "\r", ""), "$1\n"), "\n", "\n ")
|
||
|
}
|
||
|
|
||
|
func handler(w http.ResponseWriter, r *http.Request) {
|
||
|
defer r.Body.Close()
|
||
|
if err := r.ParseForm(); err != nil {
|
||
|
w.WriteHeader(http.StatusBadRequest)
|
||
|
return
|
||
|
}
|
||
|
text := r.FormValue("text")
|
||
|
if len(text) > 64<<10 {
|
||
|
w.WriteHeader(http.StatusBadRequest)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
m.Lock()
|
||
|
defer m.Unlock()
|
||
|
|
||
|
j, _ := json.Marshal(struct {
|
||
|
URI string
|
||
|
Headers http.Header
|
||
|
Form url.Values
|
||
|
}{
|
||
|
URI: r.RequestURI,
|
||
|
Headers: r.Header,
|
||
|
Form: r.Form,
|
||
|
})
|
||
|
|
||
|
if s, err := file.Stat(); err != nil {
|
||
|
log.Fatalln(err)
|
||
|
} else if s.Size()+int64(len(text)) > 64<<20 {
|
||
|
w.WriteHeader(http.StatusInternalServerError)
|
||
|
} else if r.Form.Has("submit") {
|
||
|
// <input type="submit"> should not be named, and thus received.
|
||
|
//
|
||
|
// If this is not enough to filter out most spammers, consider also:
|
||
|
// - Header: "Origin" should not be missing for POST.
|
||
|
// - Header: "Accept" should not be "*/*".
|
||
|
// - Header: "Accept-Language" and "Accept-Encoding" should be present.
|
||
|
// - Form: _charset_ should not be kept verbatim,
|
||
|
// seeing as Safari/Chromium/Firefox all pass UTF-8,
|
||
|
// in accordance with HTML5.
|
||
|
w.WriteHeader(http.StatusTeapot)
|
||
|
} else {
|
||
|
fmt.Fprintf(file, "%s %s\n %s\n",
|
||
|
time.Now().Local().Format(time.RFC1123), r.RequestURI, wrap(text))
|
||
|
if err := file.Sync(); err != nil {
|
||
|
log.Fatalln(err)
|
||
|
}
|
||
|
|
||
|
// To help filter out spammers.
|
||
|
fmt.Fprintf(requests, "%s\n", j)
|
||
|
if err := requests.Sync(); err != nil {
|
||
|
log.Fatalln(err)
|
||
|
}
|
||
|
|
||
|
fmt.Fprintln(w, "Saved.")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
if len(os.Args) != 3 {
|
||
|
log.Fatalf("Usage: %s BIND DB\n", os.Args[0])
|
||
|
}
|
||
|
|
||
|
var err error
|
||
|
if file, err = os.OpenFile(os.Args[2],
|
||
|
os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644); err != nil {
|
||
|
log.Fatalln(err)
|
||
|
}
|
||
|
if requests, err = os.OpenFile(os.Args[2]+".requests",
|
||
|
os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644); err != nil {
|
||
|
log.Fatalln(err)
|
||
|
}
|
||
|
|
||
|
http.HandleFunc("/", handler)
|
||
|
log.Fatalln(http.ListenAndServe(os.Args[1], nil))
|
||
|
}
|