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.

98 lines
2.0 KiB

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