gopher.go 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363
  1. // Package gopher provides an implementation of the Gopher protocol (RFC 1436)
  2. //
  3. // Much of the API is similar in design to the net/http package of the
  4. // standard library. To build custom Gopher servers implement handler
  5. // functions or the `Handler{}` interface. Implementing a client is as
  6. // simple as calling `gopher.Get(uri)` and passing in a `uri` such as
  7. // `"gopher://gopher.floodgap.com/"`.
  8. package gopher
  9. import (
  10. "bufio"
  11. "bytes"
  12. "context"
  13. "crypto/rand"
  14. "crypto/tls"
  15. "encoding/json"
  16. "errors"
  17. "fmt"
  18. "io"
  19. "log"
  20. "net"
  21. "net/http"
  22. "net/url"
  23. "os"
  24. "path"
  25. "path/filepath"
  26. "sort"
  27. "strconv"
  28. "strings"
  29. "sync"
  30. )
  31. // Item Types
  32. const (
  33. FILE = ItemType('0') // Item is a file
  34. DIRECTORY = ItemType('1') // Item is a directory
  35. PHONEBOOK = ItemType('2') // Item is a CSO phone-book server
  36. ERROR = ItemType('3') // Error
  37. BINHEX = ItemType('4') // Item is a BinHexed Macintosh file.
  38. DOSARCHIVE = ItemType('5') // Item is DOS binary archive of some sort. (*)
  39. UUENCODED = ItemType('6') // Item is a UNIX uuencoded file.
  40. INDEXSEARCH = ItemType('7') // Item is an Index-Search server.
  41. TELNET = ItemType('8') // Item points to a text-based telnet session.
  42. BINARY = ItemType('9') // Item is a binary file! (*)
  43. // (*) Client must read until the TCP connection is closed.
  44. REDUNDANT = ItemType('+') // Item is a redundant server
  45. TN3270 = ItemType('T') // Item points to a text-based tn3270 session.
  46. GIF = ItemType('g') // Item is a GIF format graphics file.
  47. IMAGE = ItemType('I') // Item is some kind of image file.
  48. // non-standard
  49. INFO = ItemType('i') // Item is an informational message
  50. HTML = ItemType('h') // Item is a HTML document
  51. AUDIO = ItemType('s') // Item is an Audio file
  52. PNG = ItemType('p') // Item is a PNG Image
  53. DOC = ItemType('d') // Item is a Document
  54. )
  55. const (
  56. // END represents the terminator used in directory responses
  57. END = byte('.')
  58. // TAB is the delimiter used to separate item response parts
  59. TAB = byte('\t')
  60. // CRLF is the delimiter used per line of response item
  61. CRLF = "\r\n"
  62. // DEFAULT is the default item type
  63. DEFAULT = BINARY
  64. )
  65. // contextKey is a value for use with context.WithValue. It's used as
  66. // a pointer so it fits in an interface{} without allocation.
  67. type contextKey struct {
  68. name string
  69. }
  70. func (k *contextKey) String() string {
  71. return "gopher context value " + k.name
  72. }
  73. var (
  74. // ServerContextKey is a context key. It can be used in Gopher
  75. // handlers with context.WithValue to access the server that
  76. // started the handler. The associated value will be of type *Server.
  77. ServerContextKey = &contextKey{"gopher-server"}
  78. // LocalAddrContextKey is a context key. It can be used in
  79. // Gopher handlers with context.WithValue to access the address
  80. // the local address the connection arrived on.
  81. // The associated value will be of type net.Addr.
  82. LocalAddrContextKey = &contextKey{"local-addr"}
  83. )
  84. // ItemType represents the type of an item
  85. type ItemType byte
  86. // Return a human friendly represation of an ItemType
  87. func (it ItemType) String() string {
  88. switch it {
  89. case FILE:
  90. return "TXT"
  91. case DIRECTORY:
  92. return "DIR"
  93. case PHONEBOOK:
  94. return "PHO"
  95. case ERROR:
  96. return "ERR"
  97. case BINHEX:
  98. return "HEX"
  99. case DOSARCHIVE:
  100. return "ARC"
  101. case UUENCODED:
  102. return "UUE"
  103. case INDEXSEARCH:
  104. return "QRY"
  105. case TELNET:
  106. return "TEL"
  107. case BINARY:
  108. return "BIN"
  109. case REDUNDANT:
  110. return "DUP"
  111. case TN3270:
  112. return "TN3"
  113. case GIF:
  114. return "GIF"
  115. case IMAGE:
  116. return "IMG"
  117. case INFO:
  118. return "NFO"
  119. case HTML:
  120. return "HTM"
  121. case AUDIO:
  122. return "SND"
  123. case PNG:
  124. return "PNG"
  125. case DOC:
  126. return "DOC"
  127. default:
  128. return "???"
  129. }
  130. }
  131. // Item describes an entry in a directory listing.
  132. type Item struct {
  133. Type ItemType `json:"type"`
  134. Description string `json:"description"`
  135. Selector string `json:"selector"`
  136. Host string `json:"host"`
  137. Port int `json:"port"`
  138. // non-standard extensions (ignored by standard clients)
  139. Extras []string `json:"extras"`
  140. }
  141. // ParseItem parses a line of text into an item
  142. func ParseItem(line string) (item *Item, err error) {
  143. parts := strings.Split(strings.Trim(line, "\r\n"), "\t")
  144. if len(parts[0]) < 1 {
  145. return nil, errors.New("no item type: " + string(line))
  146. }
  147. item = &Item{
  148. Type: ItemType(parts[0][0]),
  149. Description: string(parts[0][1:]),
  150. Extras: make([]string, 0),
  151. }
  152. // Selector
  153. if len(parts) > 1 {
  154. item.Selector = string(parts[1])
  155. } else {
  156. item.Selector = ""
  157. }
  158. // Host
  159. if len(parts) > 2 {
  160. item.Host = string(parts[2])
  161. } else {
  162. item.Host = "null.host"
  163. }
  164. // Port
  165. if len(parts) > 3 {
  166. port, err := strconv.Atoi(string(parts[3]))
  167. if err != nil {
  168. // Ignore parsing errors for bad servers for INFO types
  169. if item.Type != INFO {
  170. return nil, err
  171. }
  172. item.Port = 0
  173. }
  174. item.Port = port
  175. } else {
  176. item.Port = 0
  177. }
  178. // Extras
  179. if len(parts) >= 4 {
  180. for _, v := range parts[4:] {
  181. item.Extras = append(item.Extras, string(v))
  182. }
  183. }
  184. return
  185. }
  186. // MarshalJSON serializes an Item into a JSON structure
  187. func (i Item) MarshalJSON() ([]byte, error) {
  188. return json.Marshal(struct {
  189. Type string `json:"type"`
  190. Description string `json:"description"`
  191. Selector string `json:"selector"`
  192. Host string `json:"host"`
  193. Port int `json:"port"`
  194. Extras []string `json:"extras"`
  195. }{
  196. Type: string(i.Type),
  197. Description: i.Description,
  198. Selector: i.Selector,
  199. Host: i.Host,
  200. Port: i.Port,
  201. Extras: i.Extras,
  202. })
  203. }
  204. // MarshalText serializes an Item into an array of bytes
  205. func (i Item) MarshalText() ([]byte, error) {
  206. b := []byte{}
  207. b = append(b, byte(i.Type))
  208. b = append(b, []byte(i.Description)...)
  209. b = append(b, TAB)
  210. b = append(b, []byte(i.Selector)...)
  211. b = append(b, TAB)
  212. b = append(b, []byte(i.Host)...)
  213. b = append(b, TAB)
  214. b = append(b, []byte(strconv.Itoa(i.Port))...)
  215. for _, s := range i.Extras {
  216. b = append(b, TAB)
  217. b = append(b, []byte(s)...)
  218. }
  219. b = append(b, []byte(CRLF)...)
  220. return b, nil
  221. }
  222. func (i Item) isDirectoryLike() bool {
  223. switch i.Type {
  224. case DIRECTORY:
  225. return true
  226. case INDEXSEARCH:
  227. return true
  228. default:
  229. return false
  230. }
  231. }
  232. // Directory representes a Gopher Menu of Items
  233. type Directory struct {
  234. Items []Item `json:"items"`
  235. }
  236. // ToJSON returns the Directory as JSON bytes
  237. func (d *Directory) ToJSON() ([]byte, error) {
  238. jsonBytes, err := json.Marshal(d)
  239. return jsonBytes, err
  240. }
  241. // ToText returns the Directory as UTF-8 encoded bytes
  242. func (d *Directory) ToText() ([]byte, error) {
  243. var buffer bytes.Buffer
  244. for _, i := range d.Items {
  245. val, err := i.MarshalText()
  246. if err != nil {
  247. return nil, err
  248. }
  249. buffer.Write(val)
  250. }
  251. return buffer.Bytes(), nil
  252. }
  253. // Response represents a Gopher resource that
  254. // Items contains a non-empty array of Item(s)
  255. // for directory types, otherwise the Body
  256. // contains the fetched resource (file, image, etc).
  257. type Response struct {
  258. Type ItemType
  259. Dir Directory
  260. Body io.Reader
  261. }
  262. // Get fetches a Gopher resource by URI
  263. func Get(uri string) (*Response, error) {
  264. u, err := url.Parse(uri)
  265. if err != nil {
  266. return nil, err
  267. }
  268. if u.Scheme != "gopher" {
  269. return nil, errors.New("invalid scheme for uri")
  270. }
  271. var (
  272. host string
  273. port int
  274. )
  275. hostport := strings.Split(u.Host, ":")
  276. if len(hostport) == 2 {
  277. host = hostport[0]
  278. n, err := strconv.ParseInt(hostport[1], 10, 32)
  279. if err != nil {
  280. return nil, err
  281. }
  282. port = int(n)
  283. } else {
  284. host, port = hostport[0], 70
  285. }
  286. var (
  287. Type ItemType
  288. Selector string
  289. )
  290. path := strings.TrimPrefix(u.Path, "/")
  291. if len(path) > 2 {
  292. Type = ItemType(path[0])
  293. Selector = path[1:]
  294. if u.RawQuery != "" {
  295. Selector += "\t" + u.RawQuery
  296. }
  297. } else if len(path) == 1 {
  298. Type = ItemType(path[0])
  299. Selector = ""
  300. } else {
  301. Type = ItemType(DIRECTORY)
  302. Selector = ""
  303. }
  304. i := Item{Type: Type, Selector: Selector, Host: host, Port: port}
  305. res := Response{Type: i.Type}
  306. if i.isDirectoryLike() {
  307. d, err := i.FetchDirectory()
  308. if err != nil {
  309. return nil, err
  310. }
  311. res.Dir = d
  312. } else {
  313. reader, err := i.FetchFile()
  314. if err != nil {
  315. return nil, err
  316. }
  317. res.Body = reader
  318. }
  319. return &res, nil
  320. }
  321. // FetchFile fetches data, not directory information.
  322. // Calling this on a DIRECTORY Item type
  323. // or unsupported type will return an error.
  324. func (i *Item) FetchFile() (io.Reader, error) {
  325. if i.Type == DIRECTORY {
  326. return nil, errors.New("cannot fetch a directory as a file")
  327. }
  328. conn, err := net.Dial("tcp", i.Host+":"+strconv.Itoa(i.Port))
  329. if err != nil {
  330. return nil, err
  331. }
  332. _, err = conn.Write([]byte(i.Selector + CRLF))
  333. if err != nil {
  334. conn.Close()
  335. return nil, err
  336. }
  337. return conn, nil
  338. }
  339. // FetchDirectory fetches directory information, not data.
  340. // Calling this on an Item whose type is not DIRECTORY will return an error.
  341. func (i *Item) FetchDirectory() (Directory, error) {
  342. if !i.isDirectoryLike() {
  343. return Directory{}, errors.New("cannot fetch a file as a directory")
  344. }
  345. conn, err := net.Dial("tcp", i.Host+":"+strconv.Itoa(i.Port))
  346. if err != nil {
  347. return Directory{}, err
  348. }
  349. _, err = conn.Write([]byte(i.Selector + CRLF))
  350. if err != nil {
  351. return Directory{}, err
  352. }
  353. reader := bufio.NewReader(conn)
  354. scanner := bufio.NewScanner(reader)
  355. scanner.Split(bufio.ScanLines)
  356. var items []Item
  357. for scanner.Scan() {
  358. line := strings.Trim(scanner.Text(), "\r\n")
  359. if len(line) == 0 {
  360. continue
  361. }
  362. if len(line) == 1 && line[0] == END {
  363. break
  364. }
  365. item, err := ParseItem(line)
  366. if err != nil {
  367. log.Printf("Error parsing %q: %q", line, err)
  368. continue
  369. }
  370. items = append(items, *item)
  371. }
  372. return Directory{items}, nil
  373. }
  374. // Request repsesnts an inbound request to a listening server.
  375. // LocalHost and LocalPort may be used by the Handler for local links.
  376. // These are specified in the call to ListenAndServe.
  377. type Request struct {
  378. conn net.Conn
  379. Selector string
  380. LocalHost string
  381. LocalPort int
  382. }
  383. // A Handler responds to a Gopher request.
  384. //
  385. // ServeGopher should write data or items to the ResponseWriter
  386. // and then return. Returning signals that the request is finished; it
  387. // is not valid to use the ResponseWriter concurrently with the completion
  388. // of the ServeGopher call.
  389. //
  390. // Handlers should not modify the provided request.
  391. //
  392. // If ServeGopher panics, the server (the caller of ServeGopher) assumes
  393. // that the effect of the panic was isolated to the active request.
  394. // It recovers the panic, logs a stack trace to the server error log,
  395. // and hangs up the connection.
  396. type Handler interface {
  397. ServeGopher(ResponseWriter, *Request)
  398. }
  399. // FileExtensions defines a mapping of known file extensions to gopher types
  400. var FileExtensions = map[string]ItemType{
  401. ".txt": FILE,
  402. ".gif": GIF,
  403. ".jpg": IMAGE,
  404. ".jpeg": IMAGE,
  405. ".png": IMAGE,
  406. ".html": HTML,
  407. ".ogg": AUDIO,
  408. ".mp3": AUDIO,
  409. ".wav": AUDIO,
  410. ".mod": AUDIO,
  411. ".it": AUDIO,
  412. ".xm": AUDIO,
  413. ".mid": AUDIO,
  414. ".vgm": AUDIO,
  415. ".s": FILE,
  416. ".c": FILE,
  417. ".py": FILE,
  418. ".h": FILE,
  419. ".md": FILE,
  420. ".go": FILE,
  421. ".fs": FILE,
  422. }
  423. // MimeTypes defines a mapping of known mimetypes to gopher types
  424. var MimeTypes = map[string]ItemType{
  425. "text/html": HTML,
  426. "text/*": FILE,
  427. "image/gif": GIF,
  428. "image/*": IMAGE,
  429. "audio/*": AUDIO,
  430. "application/x-tar": DOSARCHIVE,
  431. "application/x-gtar": DOSARCHIVE,
  432. "application/x-xz": DOSARCHIVE,
  433. "application/x-zip": DOSARCHIVE,
  434. "application/x-gzip": DOSARCHIVE,
  435. "application/x-bzip2": DOSARCHIVE,
  436. }
  437. func matchExtension(f os.FileInfo) ItemType {
  438. extension := strings.ToLower(filepath.Ext(f.Name()))
  439. k, ok := FileExtensions[extension]
  440. if !ok {
  441. return DEFAULT
  442. }
  443. return k
  444. }
  445. func matchMimeType(mimeType string) ItemType {
  446. for k, v := range MimeTypes {
  447. matched, err := filepath.Match(k, mimeType)
  448. if !matched || (err != nil) {
  449. continue
  450. }
  451. return v
  452. }
  453. return DEFAULT
  454. }
  455. // GetItemType returns the Gopher Type of the given path
  456. func GetItemType(p string) ItemType {
  457. fi, err := os.Stat(p)
  458. if err != nil {
  459. return DEFAULT
  460. }
  461. if fi.IsDir() {
  462. return DIRECTORY
  463. }
  464. f, err := os.Open(p)
  465. if err != nil {
  466. return matchExtension(fi)
  467. }
  468. b := make([]byte, 512)
  469. n, err := io.ReadAtLeast(f, b, 512)
  470. if (err != nil) || (n != 512) {
  471. return matchExtension(fi)
  472. }
  473. mimeType := http.DetectContentType(b)
  474. mimeParts := strings.Split(mimeType, ";")
  475. return matchMimeType(mimeParts[0])
  476. }
  477. // Server defines parameters for running a Gopher server.
  478. // A zero value for Server is valid configuration.
  479. type Server struct {
  480. Addr string // TCP address to listen on, ":gopher" if empty
  481. Handler Handler // handler to invoke, gopher.DefaultServeMux if nil
  482. Hostname string // FQDN Hostname to reach this server on
  483. }
  484. // serverHandler delegates to either the server's Handler or
  485. // DefaultServeMux and also handles "OPTIONS *" requests.
  486. type serverHandler struct {
  487. s *Server
  488. }
  489. func (sh serverHandler) ServeGopher(rw ResponseWriter, req *Request) {
  490. handler := sh.s.Handler
  491. if handler == nil {
  492. handler = DefaultServeMux
  493. }
  494. handler.ServeGopher(rw, req)
  495. }
  496. // ListenAndServe starts serving gopher requests using the given Handler.
  497. // The address passed to ListenAndServe should be an internet-accessable
  498. // domain name, optionally followed by a colon and the port number.
  499. //
  500. // If the address is not a FQDN, LocalHost as passed to the Handler
  501. // may not be accessible to clients, so links may not work.
  502. func (s *Server) ListenAndServe() error {
  503. addr := s.Addr
  504. if addr == "" {
  505. addr = ":70"
  506. }
  507. ln, err := net.Listen("tcp", addr)
  508. if err != nil {
  509. return err
  510. }
  511. return s.Serve(ln)
  512. }
  513. // ListenAndServeTLS listens on the TCP network address srv.Addr and
  514. // then calls Serve to handle requests on incoming TLS connections.
  515. // Accepted connections are configured to enable TCP keep-alives.
  516. //
  517. // Filenames containing a certificate and matching private key for the
  518. // server must be provided if neither the Server's TLSConfig.Certificates
  519. // nor TLSConfig.GetCertificate are populated. If the certificate is
  520. // signed by a certificate authority, the certFile should be the
  521. // concatenation of the server's certificate, any intermediates, and
  522. // the CA's certificate.
  523. //
  524. // If srv.Addr is blank, ":gophers" is used (port 73).
  525. //
  526. // ListenAndServeTLS always returns a non-nil error.
  527. func (s *Server) ListenAndServeTLS(certFile, keyFile string) error {
  528. addr := s.Addr
  529. if addr == "" {
  530. addr = ":73"
  531. }
  532. cert, err := tls.LoadX509KeyPair(certFile, keyFile)
  533. if err != nil {
  534. log.Fatalf("server: loadkeys: %s", err)
  535. }
  536. config := tls.Config{Certificates: []tls.Certificate{cert}}
  537. config.Rand = rand.Reader
  538. ln, err := tls.Listen("tcp", addr, &config)
  539. if err != nil {
  540. log.Fatalf("server: listen: %s", err)
  541. }
  542. return s.Serve(ln)
  543. }
  544. // Serve ...
  545. func (s *Server) Serve(l net.Listener) error {
  546. defer l.Close()
  547. ctx := context.Background()
  548. ctx = context.WithValue(ctx, ServerContextKey, s)
  549. ctx = context.WithValue(ctx, LocalAddrContextKey, l.Addr())
  550. for {
  551. rw, err := l.Accept()
  552. if err != nil {
  553. fmt.Errorf("error accepting new client: %v", err)
  554. return err
  555. }
  556. c := s.newConn(rw)
  557. go c.serve(ctx)
  558. }
  559. }
  560. // A conn represents the server side of a Gopher connection.
  561. type conn struct {
  562. // server is the server on which the connection arrived.
  563. // Immutable; never nil.
  564. server *Server
  565. // rwc is the underlying network connection.
  566. // This is never wrapped by other types and is the value given out
  567. // to CloseNotifier callers. It is usually of type *net.TCPConn or
  568. // *tls.Conn.
  569. rwc net.Conn
  570. // remoteAddr is rwc.RemoteAddr().String(). It is not populated synchronously
  571. // inside the Listener's Accept goroutine, as some implementations block.
  572. // It is populated immediately inside the (*conn).serve goroutine.
  573. // This is the value of a Handler's (*Request).RemoteAddr.
  574. remoteAddr string
  575. // tlsState is the TLS connection state when using TLS.
  576. // nil means not TLS.
  577. tlsState *tls.ConnectionState
  578. // mu guards hijackedv, use of bufr, (*response).closeNotifyCh.
  579. mu sync.Mutex
  580. }
  581. // Create new connection from rwc.
  582. func (s *Server) newConn(rwc net.Conn) *conn {
  583. c := &conn{
  584. server: s,
  585. rwc: rwc,
  586. }
  587. return c
  588. }
  589. func (c *conn) serve(ctx context.Context) {
  590. c.remoteAddr = c.rwc.RemoteAddr().String()
  591. w, err := c.readRequest(ctx)
  592. if err != nil {
  593. if err == io.EOF {
  594. return // don't reply
  595. }
  596. if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
  597. return // don't reply
  598. }
  599. io.WriteString(c.rwc, "3\tbad request\terror.host\t0")
  600. return
  601. }
  602. serverHandler{c.server}.ServeGopher(w, w.req)
  603. w.End()
  604. }
  605. func readRequest(rwc net.Conn) (req *Request, err error) {
  606. reader := bufio.NewReader(rwc)
  607. scanner := bufio.NewScanner(reader)
  608. scanner.Split(bufio.ScanLines)
  609. scanner.Scan()
  610. req = &Request{
  611. Selector: scanner.Text(),
  612. }
  613. // If empty selector, assume /
  614. if req.Selector == "" {
  615. req.Selector = "/"
  616. }
  617. // If no leading / prefix, add one
  618. if !strings.HasPrefix(req.Selector, "/") {
  619. req.Selector = "/" + req.Selector
  620. }
  621. return req, nil
  622. }
  623. func (c *conn) close() (err error) {
  624. c.mu.Lock() // while using bufr
  625. err = c.rwc.Close()
  626. c.mu.Unlock()
  627. return
  628. }
  629. func (c *conn) readRequest(ctx context.Context) (w *response, err error) {
  630. c.mu.Lock() // while using bufr
  631. req, err := readRequest(c.rwc)
  632. c.mu.Unlock()
  633. if err != nil {
  634. return nil, err
  635. }
  636. localaddr := ctx.Value(LocalAddrContextKey).(*net.TCPAddr)
  637. host, port, err := net.SplitHostPort(localaddr.String())
  638. if err != nil {
  639. return nil, err
  640. }
  641. n, err := strconv.ParseInt(port, 10, 32)
  642. if err != nil {
  643. return nil, err
  644. }
  645. server := ctx.Value(ServerContextKey).(*Server)
  646. if server.Hostname == "" {
  647. req.LocalHost = host
  648. req.LocalPort = int(n)
  649. } else {
  650. req.LocalHost = server.Hostname
  651. // TODO: Parse this from -bind option
  652. req.LocalPort = int(n)
  653. }
  654. w = &response{
  655. conn: c,
  656. req: req,
  657. }
  658. w.w = bufio.NewWriter(c.rwc)
  659. return w, nil
  660. }
  661. // ListenAndServe listens on the TCP network address addr
  662. // and then calls Serve with handler to handle requests
  663. // on incoming connections.
  664. //
  665. // A trivial example server is:
  666. //
  667. // package main
  668. //
  669. // import (
  670. // "io"
  671. // "log"
  672. //
  673. // "within.website/gopher"
  674. // )
  675. //
  676. // // hello world, the gopher server
  677. // func HelloServer(w gopher.ResponseWriter, req *gopher.Request) {
  678. // w.WriteInfo("hello, world!")
  679. // }
  680. //
  681. // func main() {
  682. // gopher.HandleFunc("/hello", HelloServer)
  683. // log.Fatal(gopher.ListenAndServe(":7000", nil))
  684. // }
  685. //
  686. // ListenAndServe always returns a non-nil error.
  687. func ListenAndServe(addr string, handler Handler) error {
  688. server := &Server{Addr: addr, Handler: handler}
  689. return server.ListenAndServe()
  690. }
  691. // ListenAndServeTLS acts identically to ListenAndServe, except that it
  692. // expects TLS connections. Additionally, files containing a certificate and
  693. // matching private key for the server must be provided. If the certificate
  694. // is signed by a certificate authority, the certFile should be the
  695. // concatenation of the server's certificate, any intermediates,
  696. // and the CA's certificate.
  697. //
  698. // A trivial example server is:
  699. //
  700. // import (
  701. // "log"
  702. //
  703. // "github.com/prologic/go-gopher",
  704. // )
  705. //
  706. // func HelloServer(w gopher.ResponseWriter, req *gopher.Request) {
  707. // w.WriteInfo("hello, world!")
  708. // }
  709. //
  710. // func main() {
  711. // gopher.HandleFunc("/", handler)
  712. // log.Printf("About to listen on 73. Go to gophers://127.0.0.1:73/")
  713. // err := gopher.ListenAndServeTLS(":73", "cert.pem", "key.pem", nil)
  714. // log.Fatal(err)
  715. // }
  716. //
  717. // One can use generate_cert.go in crypto/tls to generate cert.pem and key.pem.
  718. //
  719. // ListenAndServeTLS always returns a non-nil error.
  720. func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error {
  721. server := &Server{Addr: addr, Handler: handler}
  722. return server.ListenAndServeTLS(certFile, keyFile)
  723. }
  724. // ServeMux is a Gopher request multiplexer.
  725. // It matches the URL of each incoming request against a list of registered
  726. // patterns and calls the handler for the pattern that
  727. // most closely matches the URL.
  728. //
  729. // Patterns name fixed, rooted paths, like "/favicon.ico",
  730. // or rooted subtrees, like "/images/" (note the trailing slash).
  731. // Longer patterns take precedence over shorter ones, so that
  732. // if there are handlers registered for both "/images/"
  733. // and "/images/thumbnails/", the latter handler will be
  734. // called for paths beginning "/images/thumbnails/" and the
  735. // former will receive requests for any other paths in the
  736. // "/images/" subtree.
  737. //
  738. // Note that since a pattern ending in a slash names a rooted subtree,
  739. // the pattern "/" matches all paths not matched by other registered
  740. // patterns, not just the URL with Path == "/".
  741. //
  742. // If a subtree has been registered and a request is received naming the
  743. // subtree root without its trailing slash, ServeMux redirects that
  744. // request to the subtree root (adding the trailing slash). This behavior can
  745. // be overridden with a separate registration for the path without
  746. // the trailing slash. For example, registering "/images/" causes ServeMux
  747. // to redirect a request for "/images" to "/images/", unless "/images" has
  748. // been registered separately.
  749. //
  750. // ServeMux also takes care of sanitizing the URL request path,
  751. // redirecting any request containing . or .. elements or repeated slashes
  752. // to an equivalent, cleaner URL.
  753. type ServeMux struct {
  754. mu sync.RWMutex
  755. m map[string]muxEntry
  756. }
  757. type muxEntry struct {
  758. explicit bool
  759. h Handler
  760. pattern string
  761. }
  762. // NewServeMux allocates and returns a new ServeMux.
  763. func NewServeMux() *ServeMux { return new(ServeMux) }
  764. // DefaultServeMux is the default ServeMux used by Serve.
  765. var DefaultServeMux = &defaultServeMux
  766. var defaultServeMux ServeMux
  767. // Does selector match pattern?
  768. func selectorMatch(pattern, selector string) bool {
  769. if len(pattern) == 0 {
  770. // should not happen
  771. return false
  772. }
  773. n := len(pattern)
  774. if pattern[n-1] != '/' {
  775. return pattern == selector
  776. }
  777. return len(selector) >= n && selector[0:n] == pattern
  778. }
  779. // Return the canonical path for p, eliminating . and .. elements.
  780. func cleanPath(p string) string {
  781. if p == "" {
  782. return "/"
  783. }
  784. if p[0] != '/' {
  785. p = "/" + p
  786. }
  787. np := path.Clean(p)
  788. // path.Clean removes trailing slash except for root;
  789. // put the trailing slash back if necessary.
  790. if p[len(p)-1] == '/' && np != "/" {
  791. np += "/"
  792. }
  793. return np
  794. }
  795. // Find a handler on a handler map given a path string
  796. // Most-specific (longest) pattern wins
  797. func (mux *ServeMux) match(selector string) (h Handler, pattern string) {
  798. var n = 0
  799. for k, v := range mux.m {
  800. if !selectorMatch(k, selector) {
  801. continue
  802. }
  803. if h == nil || len(k) > n {
  804. n = len(k)
  805. h = v.h
  806. pattern = v.pattern
  807. }
  808. }
  809. return
  810. }
  811. // Handler returns the handler to use for the given request,
  812. // consulting r.Selector. It always returns
  813. // a non-nil handler.
  814. //
  815. // Handler also returns the registered pattern that matches the request.
  816. //
  817. // If there is no registered handler that applies to the request,
  818. // Handler returns a ``resource not found'' handler and an empty pattern.
  819. func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
  820. return mux.handler(r.Selector)
  821. }
  822. // handler is the main implementation of Handler.
  823. func (mux *ServeMux) handler(selector string) (h Handler, pattern string) {
  824. mux.mu.RLock()
  825. defer mux.mu.RUnlock()
  826. h, pattern = mux.match(selector)
  827. if h == nil {
  828. h, pattern = NotFoundHandler(), ""
  829. }
  830. return
  831. }
  832. // ServeGopher dispatches the request to the handler whose
  833. // pattern most closely matches the request URL.
  834. func (mux *ServeMux) ServeGopher(w ResponseWriter, r *Request) {
  835. h, _ := mux.Handler(r)
  836. h.ServeGopher(w, r)
  837. }
  838. // Handle registers the handler for the given pattern.
  839. // If a handler already exists for pattern, Handle panics.
  840. func (mux *ServeMux) Handle(pattern string, handler Handler) {
  841. mux.mu.Lock()
  842. defer mux.mu.Unlock()
  843. if pattern == "" {
  844. panic("gopher: invalid pattern " + pattern)
  845. }
  846. if handler == nil {
  847. panic("gopher: nil handler")
  848. }
  849. if mux.m[pattern].explicit {
  850. panic("gopher: multiple registrations for " + pattern)
  851. }
  852. if mux.m == nil {
  853. mux.m = make(map[string]muxEntry)
  854. }
  855. mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern}
  856. }
  857. // HandleFunc registers the handler function for the given pattern.
  858. func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
  859. mux.Handle(pattern, HandlerFunc(handler))
  860. }
  861. // The HandlerFunc type is an adapter to allow the use of
  862. // ordinary functions as Gopher handlers. If f is a function
  863. // with the appropriate signature, HandlerFunc(f) is a
  864. // Handler that calls f.
  865. type HandlerFunc func(ResponseWriter, *Request)
  866. // ServeGopher calls f(w, r).
  867. func (f HandlerFunc) ServeGopher(w ResponseWriter, r *Request) {
  868. f(w, r)
  869. }
  870. // A ResponseWriter interface is used by a Gopher handler to
  871. // construct an Gopher response.
  872. //
  873. // A ResponseWriter may not be used after the Handler.ServeGopher method
  874. // has returned.
  875. type ResponseWriter interface {
  876. // Server returns the connection's server instance
  877. Server() *Server
  878. // End ends the document by writing the terminating period and crlf
  879. End() error
  880. // Write writes the data to the connection as part of a Gopher reply.
  881. //
  882. Write([]byte) (int, error)
  883. // WriteError writes an error item
  884. WriteError(err string) error
  885. // WriteInfo writes an informational item
  886. WriteInfo(msg string) error
  887. // WriteItem writes an item
  888. WriteItem(i Item) error
  889. }
  890. // A response represents the server side of a Gopher response.
  891. type response struct {
  892. conn *conn
  893. req *Request // request for this response
  894. w *bufio.Writer // buffers output
  895. rt int
  896. }
  897. func (w *response) Server() *Server {
  898. return w.conn.server
  899. }
  900. func (w *response) Write(b []byte) (int, error) {
  901. if w.rt == 0 {
  902. w.rt = 1
  903. }
  904. if w.rt != 1 {
  905. return 0, errors.New("cannot write document data to a directory")
  906. }
  907. return w.w.Write(b)
  908. }
  909. func (w *response) WriteError(err string) error {
  910. if w.rt == 0 {
  911. w.rt = 2
  912. }
  913. if w.rt != 2 {
  914. _, e := w.w.Write([]byte(err))
  915. return e
  916. }
  917. i := Item{
  918. Type: ERROR,
  919. Description: err,
  920. Host: "error.host",
  921. Port: 1,
  922. }
  923. return w.WriteItem(i)
  924. }
  925. func (w *response) WriteInfo(msg string) error {
  926. if w.rt == 0 {
  927. w.rt = 2
  928. }
  929. if w.rt != 2 {
  930. _, e := w.w.Write([]byte(msg))
  931. return e
  932. }
  933. i := Item{
  934. Type: INFO,
  935. Description: msg,
  936. Host: "error.host",
  937. Port: 1,
  938. }
  939. return w.WriteItem(i)
  940. }
  941. func (w *response) WriteItem(i Item) error {
  942. if w.rt == 0 {
  943. w.rt = 2
  944. }
  945. if w.rt != 2 {
  946. return errors.New("cannot write directory data to a document")
  947. }
  948. if i.Host == "" && i.Port == 0 {
  949. i.Host = w.req.LocalHost
  950. i.Port = w.req.LocalPort
  951. }
  952. b, err := i.MarshalText()
  953. if err != nil {
  954. return err
  955. }
  956. _, err = w.w.Write(b)
  957. if err != nil {
  958. return err
  959. }
  960. return nil
  961. }
  962. func (w *response) End() (err error) {
  963. if w.rt == 2 {
  964. _, err = w.w.Write(append([]byte{END}, CRLF...))
  965. if err != nil {
  966. return
  967. }
  968. }
  969. err = w.w.Flush()
  970. if err != nil {
  971. return
  972. }
  973. err = w.conn.close()
  974. if err != nil {
  975. return
  976. }
  977. return
  978. }
  979. // Helper handlers
  980. // Error replies to the request with the specified error message.
  981. // It does not otherwise end the request; the caller should ensure no further
  982. // writes are done to w.
  983. // The error message should be plain text.
  984. func Error(w ResponseWriter, error string) {
  985. w.WriteError(error)
  986. }
  987. // NotFound replies to the request with an resouce not found error item.
  988. func NotFound(w ResponseWriter, r *Request) {
  989. Error(w, "resource not found")
  990. }
  991. // NotFoundHandler returns a simple request handler
  992. // that replies to each request with a ``resource page not found'' reply.
  993. func NotFoundHandler() Handler { return HandlerFunc(NotFound) }
  994. type fileHandler struct {
  995. root FileSystem
  996. }
  997. // FileServer returns a handler that serves Gopher requests
  998. // with the contents of the file system rooted at root.
  999. //
  1000. // To use the operating system's file system implementation,
  1001. // use gopher.Dir:
  1002. //
  1003. // gopher.Handle("/", gopher.FileServer(gopher.Dir("/tmp")))
  1004. func FileServer(root FileSystem) Handler {
  1005. return &fileHandler{root}
  1006. }
  1007. func (f *fileHandler) ServeGopher(w ResponseWriter, r *Request) {
  1008. upath := r.Selector
  1009. if !strings.HasPrefix(upath, "/") {
  1010. upath = "/" + upath
  1011. r.Selector = upath
  1012. }
  1013. serveFile(w, r, f.root, path.Clean(upath))
  1014. }
  1015. // A Dir implements FileSystem using the native file system restricted to a
  1016. // specific directory tree.
  1017. //
  1018. // While the FileSystem.Open method takes '/'-separated paths, a Dir's string
  1019. // value is a filename on the native file system, not a URL, so it is separated
  1020. // by filepath.Separator, which isn't necessarily '/'.
  1021. //
  1022. // An empty Dir is treated as ".".
  1023. type Dir string
  1024. // Name returns the directory
  1025. func (d Dir) Name() string {
  1026. return string(d)
  1027. }
  1028. // Open opens the directory
  1029. func (d Dir) Open(name string) (File, error) {
  1030. if filepath.Separator != '/' &&
  1031. strings.ContainsRune(name, filepath.Separator) ||
  1032. strings.Contains(name, "\x00") {
  1033. return nil, errors.New("gopher: invalid character in file path")
  1034. }
  1035. dir := string(d)
  1036. if dir == "" {
  1037. dir = "."
  1038. }
  1039. f, err := os.Open(
  1040. filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name))),
  1041. )
  1042. if err != nil {
  1043. return nil, err
  1044. }
  1045. return f, nil
  1046. }
  1047. // A FileSystem implements access to a collection of named files.
  1048. // The elements in a file path are separated by slash ('/', U+002F)
  1049. // characters, regardless of host operating system convention.
  1050. type FileSystem interface {
  1051. Name() string
  1052. Open(name string) (File, error)
  1053. }
  1054. // A File is returned by a FileSystem's Open method and can be
  1055. // served by the FileServer implementation.
  1056. //
  1057. // The methods should behave the same as those on an *os.File.
  1058. type File interface {
  1059. io.Closer
  1060. io.Reader
  1061. io.Seeker
  1062. Readdir(count int) ([]os.FileInfo, error)
  1063. Stat() (os.FileInfo, error)
  1064. }
  1065. func dirList(w ResponseWriter, r *Request, f File, fs FileSystem) {
  1066. root := fs.Name()
  1067. fullpath := f.(*os.File).Name()
  1068. files, err := f.Readdir(-1)
  1069. if err != nil {
  1070. // TODO: log err.Error() to the Server.ErrorLog, once it's possible
  1071. // for a handler to get at its Server via the ResponseWriter.
  1072. Error(w, "Error reading directory")
  1073. return
  1074. }
  1075. sort.Sort(byName(files))
  1076. for _, file := range files {
  1077. if file.Name()[0] == '.' {
  1078. continue
  1079. }
  1080. if file.Mode()&os.ModeDir != 0 {
  1081. pathname, err := filepath.Rel(
  1082. root,
  1083. path.Join(fullpath, file.Name()),
  1084. )
  1085. if err != nil {
  1086. Error(w, "Error reading directory")
  1087. return
  1088. }
  1089. w.WriteItem(Item{
  1090. Type: DIRECTORY,
  1091. Description: file.Name(),
  1092. Selector: pathname,
  1093. Host: r.LocalHost,
  1094. Port: r.LocalPort,
  1095. })
  1096. } else if file.Mode()&os.ModeType == 0 {
  1097. pathname, err := filepath.Rel(
  1098. root,
  1099. path.Join(fullpath, file.Name()),
  1100. )
  1101. if err != nil {
  1102. Error(w, "Error reading directory")
  1103. return
  1104. }
  1105. itemtype := GetItemType(path.Join(fullpath, file.Name()))
  1106. w.WriteItem(Item{
  1107. Type: itemtype,
  1108. Description: file.Name(),
  1109. Selector: pathname,
  1110. Host: r.LocalHost,
  1111. Port: r.LocalPort,
  1112. })
  1113. }
  1114. }
  1115. }
  1116. type byName []os.FileInfo
  1117. func (s byName) Len() int { return len(s) }
  1118. func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() }
  1119. func (s byName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  1120. // name is '/'-separated, not filepath.Separator.
  1121. func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string) {
  1122. const gophermapFile = "/gophermap"
  1123. f, err := fs.Open(name)
  1124. if err != nil {
  1125. Error(w, err.Error())
  1126. return
  1127. }
  1128. defer f.Close()
  1129. d, err := f.Stat()
  1130. if err != nil {
  1131. Error(w, err.Error())
  1132. return
  1133. }
  1134. // use contents of gophermap for directory, if present
  1135. if d.IsDir() {
  1136. gophermap := strings.TrimSuffix(name, "/") + gophermapFile
  1137. ff, err := fs.Open(gophermap)
  1138. if err == nil {
  1139. defer ff.Close()
  1140. dd, err := ff.Stat()
  1141. if err == nil {
  1142. name = gophermap
  1143. d = dd
  1144. f = ff
  1145. }
  1146. }
  1147. }
  1148. // Still a directory? (we didn't find a gophermap file)
  1149. if d.IsDir() {
  1150. dirList(w, r, f, fs)
  1151. return
  1152. }
  1153. serveContent(w, r, f)
  1154. }
  1155. // content must be seeked to the beginning of the file.
  1156. func serveContent(w ResponseWriter, r *Request, content io.ReadSeeker) {
  1157. io.Copy(w, content)
  1158. }
  1159. // Handle registers the handler for the given pattern
  1160. // in the DefaultServeMux.
  1161. // The documentation for ServeMux explains how patterns are matched.
  1162. func Handle(pattern string, handler Handler) {
  1163. DefaultServeMux.Handle(pattern, handler)
  1164. }
  1165. // HandleFunc registers the handler function for the given pattern
  1166. // in the DefaultServeMux.
  1167. // The documentation for ServeMux explains how patterns are matched.
  1168. func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
  1169. DefaultServeMux.HandleFunc(pattern, handler)
  1170. }