|
|
@@ -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) |
|
|
|
} |