commit aff3a23ea2348ff5a1d9400ce1ed7c30df2dd6d0 Author: Matt Baer Date: Mon Feb 2 22:39:07 2015 -0500 Telnet server for nerds.write.as diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b72f9be --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*~ +*.swp diff --git a/banner.txt b/banner.txt new file mode 100644 index 0000000..c3fa373 --- /dev/null +++ b/banner.txt @@ -0,0 +1,13 @@ + + + .--. __.....__ + _ _ |__| .-'' '. + /\ \\ /.-,.--..--. .| / .-''"'-. `. + `\\ //\\ //| .-. | | .' |_/ /________\ \ __ + \`// \'/ | | | | |.' | | .:--.'. _ + \| |/ | | | | '--. .-\ .-------------' / | \ | .' | + ' | | '-| | | | \ '-.____...---,.--.`" __ | | . | / + | | |__| | | `. .// \.'.''| | .'.'| |// + | | | '.' `''-...... -' \\ / / | |.'.'.-' / + |_| | / `'--'\ \._,\ '.' \_.' + `'-' `--' `" diff --git a/server.go b/server.go new file mode 100644 index 0000000..4ebf62b --- /dev/null +++ b/server.go @@ -0,0 +1,174 @@ +package main + +import ( + "fmt" + "net" + "bytes" + "io/ioutil" + "crypto/rand" + "io" + "os" + "os/exec" + "strings" +) + +var ( + banner []byte +) + +const ( + colBlue = "\033[0;34m" + colGreen = "\033[0;32m" + colBGreen = "\033[1;32m" + colCyan = "\033[0;36m" + colBRed = "\033[1;31m" + colBold = "\033[1;37m" + noCol = "\033[0m" + + nameLen = 12 + outDir = "/var/write/" + bannerDir = "./" + hr = "————————————————————————————————————————————————————————————————————————————————" +) + +func main() { + ln, err := net.Listen("tcp", ":9727") + if err != nil { + panic(err) + } + fmt.Println("Listening on localhost:9727") + + fmt.Print("Initializing...") + banner, err = ioutil.ReadFile(bannerDir + "/banner.txt") + if err != nil { + fmt.Println(err) + } + fmt.Println("DONE") + + for { + conn, err := ln.Accept() + if err != nil { + fmt.Println(err) + continue + } + + go handleConnection(conn) + } +} + +func output(c net.Conn, m string) bool { + _, err := c.Write([]byte(m)) + if err != nil { + c.Close() + return false + } + return true +} + +func outputBytes(c net.Conn, m []byte) bool { + _, err := c.Write(m) + if err != nil { + c.Close() + return false + } + return true +} + +func handleConnection(c net.Conn) { + outputBytes(c, banner) + output(c, fmt.Sprintf("\n%sWelcome to write.as!%s\n", colBGreen, noCol)) + output(c, fmt.Sprintf("If this is freaking you out, you can get notified of the %sbrowser-based%s launch\ninstead at https://write.as.\n\n", colBold, noCol)) + + waitForEnter(c) + + c.Close() + + fmt.Printf("Connection from %v closed.\n", c.RemoteAddr()) +} + +func waitForEnter(c net.Conn) { + b := make([]byte, 4) + + output(c, fmt.Sprintf("%sPress Enter to continue...%s\n", colBRed, noCol)) + for { + n, err := c.Read(b) + if bytes.IndexRune(b[0:n], '\n') > -1 { + break + } + if err != nil || n == 0 { + c.Close() + break + } + } + + output(c, fmt.Sprintf("Enter anything you like.\nPress %sCtrl-D%s to publish and quit.\n%s\n", colBold, noCol, hr)) + readInput(c) +} + +func checkExit(b []byte, n int) bool { + return n > 0 && bytes.IndexRune(b[0:n], '\n') == -1 +} + +func readInput(c net.Conn) { + defer c.Close() + + b := make([]byte, 4096) + + var post bytes.Buffer + + for { + n, err := c.Read(b) + post.Write(b[0:n]) + + if checkExit(b, n) { + file, err := savePost(post.Bytes()) + if err != nil { + fmt.Printf("There was an error saving: %s\n", err) + output(c, "Something went terribly wrong, sorry. Try again later?\n\n") + break + } + output(c, fmt.Sprintf("\n%s\nPosted to %shttp://nerds.write.as/%s%s\nPosting to secure site...", hr, colBlue, file, noCol)) + exec.Command("rsync", "-ptgou", outDir + file, "www:").Run() + output(c, fmt.Sprintf("\nPosted! View at %shttps://write.as/%s%s\nSee you later.\n\n", colBlue, file, noCol)) + break + } + + if err != nil || n == 0 { + break + } + } +} + +func savePost(post []byte) (string, error) { + filename := generateFileName() + f, err := os.Create(outDir + filename) + + defer f.Close() + + if err != nil { + fmt.Println(err) + } + _, err = io.WriteString(f, stripCtlAndExtFromUTF8(string(post))) + + return filename, err +} + +func generateFileName() string { + c := nameLen + var dictionary string = "0123456789abcdefghijklmnopqrstuvwxyz" + var bytes = make([]byte, c) + rand.Read(bytes) + for k, v := range bytes { + bytes[k] = dictionary[v%byte(len(dictionary))] + } + return string(bytes) +} + +func stripCtlAndExtFromUTF8(str string) string { + return strings.Map(func(r rune) rune { + if r == 10 || r == 13 || (r >= 32 && r < 255) { + return r + } + return -1 + }, str) +}