Simple telnet server for write.as http://nerds.write.as
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

178 regels
3.9 KiB

  1. package main
  2. import (
  3. "bytes"
  4. "flag"
  5. "fmt"
  6. "io/ioutil"
  7. "net"
  8. "os/exec"
  9. "github.com/writeas/writeas-telnet/store"
  10. )
  11. var (
  12. banner []byte
  13. outDir string
  14. staticDir string
  15. debugging bool
  16. rsyncHost string
  17. )
  18. const (
  19. colBlue = "\033[0;34m"
  20. colGreen = "\033[0;32m"
  21. colBGreen = "\033[1;32m"
  22. colCyan = "\033[0;36m"
  23. colBRed = "\033[1;31m"
  24. colBold = "\033[1;37m"
  25. noCol = "\033[0m"
  26. hr = "————————————————————————————————————————————————————————————————————————————————"
  27. )
  28. func main() {
  29. // Get any arguments
  30. outDirPtr := flag.String("o", "/var/write", "Directory where text files will be stored.")
  31. staticDirPtr := flag.String("s", "./static", "Directory where required static files exist.")
  32. rsyncHostPtr := flag.String("h", "", "Hostname of the server to rsync saved files to.")
  33. portPtr := flag.Int("p", 2323, "Port to listen on.")
  34. debugPtr := flag.Bool("debug", false, "Enables garrulous debug logging.")
  35. flag.Parse()
  36. outDir = *outDirPtr
  37. staticDir = *staticDirPtr
  38. rsyncHost = *rsyncHostPtr
  39. debugging = *debugPtr
  40. fmt.Print("\nCONFIG:\n")
  41. fmt.Printf("Output directory : %s\n", outDir)
  42. fmt.Printf("Static directory : %s\n", staticDir)
  43. fmt.Printf("rsync host : %s\n", rsyncHost)
  44. fmt.Printf("Debugging enabled : %t\n\n", debugging)
  45. fmt.Print("Initializing...")
  46. var err error
  47. banner, err = ioutil.ReadFile(staticDir + "/banner.txt")
  48. if err != nil {
  49. fmt.Println(err)
  50. }
  51. fmt.Println("DONE")
  52. ln, err := net.Listen("tcp", fmt.Sprintf(":%d", *portPtr))
  53. if err != nil {
  54. panic(err)
  55. }
  56. fmt.Printf("Listening on localhost:%d\n", *portPtr)
  57. for {
  58. conn, err := ln.Accept()
  59. if err != nil {
  60. fmt.Println(err)
  61. continue
  62. }
  63. go handleConnection(conn)
  64. }
  65. }
  66. func output(c net.Conn, m string) bool {
  67. _, err := c.Write([]byte(m))
  68. if err != nil {
  69. c.Close()
  70. return false
  71. }
  72. return true
  73. }
  74. func outputBytes(c net.Conn, m []byte) bool {
  75. _, err := c.Write(m)
  76. if err != nil {
  77. c.Close()
  78. return false
  79. }
  80. return true
  81. }
  82. func handleConnection(c net.Conn) {
  83. outputBytes(c, banner)
  84. output(c, fmt.Sprintf("\n%sWelcome to write.as!%s\n", colBGreen, noCol))
  85. 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))
  86. waitForEnter(c)
  87. c.Close()
  88. fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
  89. }
  90. func waitForEnter(c net.Conn) {
  91. b := make([]byte, 4)
  92. output(c, fmt.Sprintf("%sPress Enter to continue...%s\n", colBRed, noCol))
  93. for {
  94. n, err := c.Read(b)
  95. if debugging {
  96. fmt.Print(b[0:n])
  97. fmt.Printf("\n%d: %s\n", n, b[0:n])
  98. }
  99. if bytes.IndexRune(b[0:n], '\n') > -1 {
  100. break
  101. }
  102. if err != nil || n == 0 {
  103. c.Close()
  104. break
  105. }
  106. }
  107. output(c, fmt.Sprintf("Enter anything you like.\nPress %sCtrl-D%s to publish and quit.\n%s\n", colBold, noCol, hr))
  108. readInput(c)
  109. }
  110. func checkExit(b []byte, n int) bool {
  111. return n > 0 && bytes.IndexRune(b[0:n], '\n') == -1
  112. }
  113. func readInput(c net.Conn) {
  114. defer c.Close()
  115. b := make([]byte, 4096)
  116. var post bytes.Buffer
  117. for {
  118. n, err := c.Read(b)
  119. post.Write(b[0:n])
  120. if debugging {
  121. fmt.Print(b[0:n])
  122. fmt.Printf("\n%d: %s\n", n, b[0:n])
  123. }
  124. if checkExit(b, n) {
  125. file, err := store.SavePost(outDir, post.Bytes())
  126. if err != nil {
  127. fmt.Printf("There was an error saving: %s\n", err)
  128. output(c, "Something went terribly wrong, sorry. Try again later?\n\n")
  129. break
  130. }
  131. output(c, fmt.Sprintf("\n%s\nPosted to %shttp://nerds.write.as/%s%s", hr, colBlue, file, noCol))
  132. if rsyncHost != "" {
  133. output(c, "\nPosting to secure site...")
  134. exec.Command("rsync", "-ptgou", outDir+"/"+file, rsyncHost+":").Run()
  135. output(c, fmt.Sprintf("\nPosted! View at %shttps://write.as/%s%s", colBlue, file, noCol))
  136. }
  137. output(c, "\nSee you later.\n\n")
  138. break
  139. }
  140. if err != nil || n == 0 {
  141. break
  142. }
  143. }
  144. }