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.

165 lines
3.4 KiB

  1. package main
  2. import (
  3. "archive/tar"
  4. "archive/zip"
  5. "compress/bzip2"
  6. "compress/gzip"
  7. "crypto/sha256"
  8. "encoding/hex"
  9. "errors"
  10. "io"
  11. "sort"
  12. "time"
  13. "unicode"
  14. "github.com/andreimarcu/linx-server/backends"
  15. "github.com/andreimarcu/linx-server/expiry"
  16. "github.com/dchest/uniuri"
  17. "gopkg.in/h2non/filetype.v1"
  18. )
  19. var NotFoundErr = errors.New("File not found.")
  20. func generateMetadata(fName string, exp time.Time, delKey string) (m backends.Metadata, err error) {
  21. file, err := fileBackend.Open(fName)
  22. if err != nil {
  23. return
  24. }
  25. defer file.Close()
  26. m.Size, err = fileBackend.Size(fName)
  27. if err != nil {
  28. return
  29. }
  30. m.Expiry = exp
  31. if delKey == "" {
  32. m.DeleteKey = uniuri.NewLen(30)
  33. } else {
  34. m.DeleteKey = delKey
  35. }
  36. // Get first 512 bytes for mimetype detection
  37. header := make([]byte, 512)
  38. file.Read(header)
  39. kind, err := filetype.Match(header)
  40. if err != nil {
  41. m.Mimetype = "application/octet-stream"
  42. } else {
  43. m.Mimetype = kind.MIME.Value
  44. }
  45. if m.Mimetype == "" {
  46. // Check if the file seems anything like text
  47. if printable(header) {
  48. m.Mimetype = "text/plain"
  49. } else {
  50. m.Mimetype = "application/octet-stream"
  51. }
  52. }
  53. // Compute the sha256sum
  54. hasher := sha256.New()
  55. file.Seek(0, 0)
  56. _, err = io.Copy(hasher, file)
  57. if err == nil {
  58. m.Sha256sum = hex.EncodeToString(hasher.Sum(nil))
  59. }
  60. file.Seek(0, 0)
  61. // If archive, grab list of filenames
  62. if m.Mimetype == "application/x-tar" {
  63. tReadr := tar.NewReader(file)
  64. for {
  65. hdr, err := tReadr.Next()
  66. if err == io.EOF || err != nil {
  67. break
  68. }
  69. if hdr.Typeflag == tar.TypeDir || hdr.Typeflag == tar.TypeReg {
  70. m.ArchiveFiles = append(m.ArchiveFiles, hdr.Name)
  71. }
  72. }
  73. sort.Strings(m.ArchiveFiles)
  74. } else if m.Mimetype == "application/x-gzip" {
  75. gzf, err := gzip.NewReader(file)
  76. if err == nil {
  77. tReadr := tar.NewReader(gzf)
  78. for {
  79. hdr, err := tReadr.Next()
  80. if err == io.EOF || err != nil {
  81. break
  82. }
  83. if hdr.Typeflag == tar.TypeDir || hdr.Typeflag == tar.TypeReg {
  84. m.ArchiveFiles = append(m.ArchiveFiles, hdr.Name)
  85. }
  86. }
  87. sort.Strings(m.ArchiveFiles)
  88. }
  89. } else if m.Mimetype == "application/x-bzip" {
  90. bzf := bzip2.NewReader(file)
  91. tReadr := tar.NewReader(bzf)
  92. for {
  93. hdr, err := tReadr.Next()
  94. if err == io.EOF || err != nil {
  95. break
  96. }
  97. if hdr.Typeflag == tar.TypeDir || hdr.Typeflag == tar.TypeReg {
  98. m.ArchiveFiles = append(m.ArchiveFiles, hdr.Name)
  99. }
  100. }
  101. sort.Strings(m.ArchiveFiles)
  102. } else if m.Mimetype == "application/zip" {
  103. zf, err := zip.NewReader(file, m.Size)
  104. if err == nil {
  105. for _, f := range zf.File {
  106. m.ArchiveFiles = append(m.ArchiveFiles, f.Name)
  107. }
  108. }
  109. sort.Strings(m.ArchiveFiles)
  110. }
  111. return
  112. }
  113. func metadataWrite(filename string, metadata *backends.Metadata) error {
  114. return metaBackend.Put(filename, metadata)
  115. }
  116. func metadataRead(filename string) (metadata backends.Metadata, err error) {
  117. metadata, err = metaBackend.Get(filename)
  118. if err != nil {
  119. // Metadata does not exist, generate one
  120. newMData, err := generateMetadata(filename, expiry.NeverExpire, "")
  121. if err != nil {
  122. return metadata, err
  123. }
  124. metadataWrite(filename, &newMData)
  125. metadata, err = metaBackend.Get(filename)
  126. }
  127. return
  128. }
  129. func printable(data []byte) bool {
  130. for i, b := range data {
  131. r := rune(b)
  132. // A null terminator that's not at the beginning of the file
  133. if r == 0 && i == 0 {
  134. return false
  135. } else if r == 0 && i < 0 {
  136. continue
  137. }
  138. if r > unicode.MaxASCII {
  139. return false
  140. }
  141. }
  142. return true
  143. }