Contains the Concourse pipeline definition for building a line-server container
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.

99 lines
1.9 KiB

  1. package main
  2. import (
  3. "bytes"
  4. "crypto/sha1"
  5. "fmt"
  6. "io"
  7. "net/http"
  8. "os"
  9. "path"
  10. "time"
  11. "github.com/zeebo/bencode"
  12. "github.com/zenazn/goji/web"
  13. )
  14. const (
  15. TORRENT_PIECE_LENGTH = 262144
  16. )
  17. type TorrentInfo struct {
  18. PieceLength int `bencode:"piece length"`
  19. Pieces []byte `bencode:"pieces"`
  20. Name string `bencode:"name"`
  21. Length int `bencode:"length"`
  22. }
  23. type Torrent struct {
  24. Encoding string `bencode:"encoding"`
  25. Info TorrentInfo `bencode:"info"`
  26. UrlList []string `bencode:"url-list"`
  27. }
  28. func CreateTorrent(fileName string, filePath string) ([]byte, error) {
  29. chunk := make([]byte, TORRENT_PIECE_LENGTH)
  30. var pieces []byte
  31. length := 0
  32. f, err := os.Open(filePath)
  33. if err != nil {
  34. return []byte{}, err
  35. }
  36. for {
  37. n, err := f.Read(chunk)
  38. if err == io.EOF {
  39. break
  40. } else if err != nil {
  41. return []byte{}, err
  42. }
  43. length += n
  44. h := sha1.New()
  45. h.Write(chunk)
  46. pieces = append(pieces, h.Sum(nil)...)
  47. }
  48. f.Close()
  49. torrent := &Torrent{
  50. Encoding: "UTF-8",
  51. Info: TorrentInfo{
  52. PieceLength: TORRENT_PIECE_LENGTH,
  53. Pieces: pieces,
  54. Name: fileName,
  55. Length: length,
  56. },
  57. UrlList: []string{fmt.Sprintf("%sselif/%s", Config.siteURL, fileName)},
  58. }
  59. data, err := bencode.EncodeBytes(torrent)
  60. if err != nil {
  61. return []byte{}, err
  62. }
  63. return data, nil
  64. }
  65. func fileTorrentHandler(c web.C, w http.ResponseWriter, r *http.Request) {
  66. fileName := c.URLParams["name"]
  67. filePath := path.Join(Config.filesDir, fileName)
  68. if !fileExistsAndNotExpired(fileName) {
  69. notFoundHandler(c, w, r)
  70. return
  71. }
  72. encoded, err := CreateTorrent(fileName, filePath)
  73. if err != nil {
  74. oopsHandler(c, w, r) // 500 - creating torrent failed
  75. return
  76. }
  77. w.Header().Set(`Content-Disposition`, fmt.Sprintf(`attachment; filename="%s.torrent"`, fileName))
  78. http.ServeContent(w, r, "", time.Now(), bytes.NewReader(encoded))
  79. }
  80. // vim:set ts=8 sw=8 noet: