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.

188 lines
4.2 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. "encoding/json"
  10. "errors"
  11. "io"
  12. "io/ioutil"
  13. "os"
  14. "path"
  15. "sort"
  16. "time"
  17. "bitbucket.org/taruti/mimemagic"
  18. "github.com/dchest/uniuri"
  19. )
  20. type MetadataJSON struct {
  21. DeleteKey string `json:"delete_key"`
  22. Sha256sum string `json:"sha256sum"`
  23. Mimetype string `json:"mimetype"`
  24. Size int64 `json:"size"`
  25. Expiry int64 `json:"expiry"`
  26. ArchiveFiles []string `json:"archive_files,omitempty"`
  27. }
  28. type Metadata struct {
  29. DeleteKey string
  30. Sha256sum string
  31. Mimetype string
  32. Size int64
  33. Expiry time.Time
  34. ArchiveFiles []string
  35. }
  36. var NotFoundErr = errors.New("File not found.")
  37. var BadMetadata = errors.New("Corrupted metadata.")
  38. func generateMetadata(fName string, exp time.Time, delKey string) (m Metadata, err error) {
  39. file, err := os.Open(path.Join(Config.filesDir, fName))
  40. fileInfo, err := os.Stat(path.Join(Config.filesDir, fName))
  41. if err != nil {
  42. return
  43. }
  44. defer file.Close()
  45. m.Size = fileInfo.Size()
  46. m.Expiry = exp
  47. if delKey == "" {
  48. m.DeleteKey = uniuri.NewLen(30)
  49. } else {
  50. m.DeleteKey = delKey
  51. }
  52. // Get first 512 bytes for mimetype detection
  53. header := make([]byte, 512)
  54. file.Read(header)
  55. m.Mimetype = mimemagic.Match("", header)
  56. // Compute the sha256sum
  57. hasher := sha256.New()
  58. file.Seek(0, 0)
  59. _, err = io.Copy(hasher, file)
  60. if err == nil {
  61. m.Sha256sum = hex.EncodeToString(hasher.Sum(nil))
  62. }
  63. file.Seek(0, 0)
  64. // If archive, grab list of filenames
  65. if m.Mimetype == "application/x-tar" {
  66. tReadr := tar.NewReader(file)
  67. for {
  68. hdr, err := tReadr.Next()
  69. if err == io.EOF || err != nil {
  70. break
  71. }
  72. if hdr.Typeflag == tar.TypeDir || hdr.Typeflag == tar.TypeReg {
  73. m.ArchiveFiles = append(m.ArchiveFiles, hdr.Name)
  74. }
  75. }
  76. sort.Strings(m.ArchiveFiles)
  77. } else if m.Mimetype == "application/x-gzip" {
  78. gzf, err := gzip.NewReader(file)
  79. if err == nil {
  80. tReadr := tar.NewReader(gzf)
  81. for {
  82. hdr, err := tReadr.Next()
  83. if err == io.EOF || err != nil {
  84. break
  85. }
  86. if hdr.Typeflag == tar.TypeDir || hdr.Typeflag == tar.TypeReg {
  87. m.ArchiveFiles = append(m.ArchiveFiles, hdr.Name)
  88. }
  89. }
  90. sort.Strings(m.ArchiveFiles)
  91. }
  92. } else if m.Mimetype == "application/x-bzip" {
  93. bzf := bzip2.NewReader(file)
  94. tReadr := tar.NewReader(bzf)
  95. for {
  96. hdr, err := tReadr.Next()
  97. if err == io.EOF || err != nil {
  98. break
  99. }
  100. if hdr.Typeflag == tar.TypeDir || hdr.Typeflag == tar.TypeReg {
  101. m.ArchiveFiles = append(m.ArchiveFiles, hdr.Name)
  102. }
  103. }
  104. sort.Strings(m.ArchiveFiles)
  105. } else if m.Mimetype == "application/zip" {
  106. zf, err := zip.NewReader(file, m.Size)
  107. if err == nil {
  108. for _, f := range zf.File {
  109. m.ArchiveFiles = append(m.ArchiveFiles, f.Name)
  110. }
  111. }
  112. sort.Strings(m.ArchiveFiles)
  113. }
  114. return
  115. }
  116. func metadataWrite(filename string, metadata *Metadata) error {
  117. file, err := os.Create(path.Join(Config.metaDir, filename))
  118. if err != nil {
  119. return err
  120. }
  121. defer file.Close()
  122. mjson := MetadataJSON{}
  123. mjson.DeleteKey = metadata.DeleteKey
  124. mjson.Mimetype = metadata.Mimetype
  125. mjson.ArchiveFiles = metadata.ArchiveFiles
  126. mjson.Sha256sum = metadata.Sha256sum
  127. mjson.Expiry = metadata.Expiry.Unix()
  128. mjson.Size = metadata.Size
  129. byt, err := json.Marshal(mjson)
  130. if err != nil {
  131. return err
  132. }
  133. _, err = file.Write(byt)
  134. if err != nil {
  135. return err
  136. }
  137. return nil
  138. }
  139. func metadataRead(filename string) (metadata Metadata, err error) {
  140. b, err := ioutil.ReadFile(path.Join(Config.metaDir, filename))
  141. if err != nil {
  142. // Metadata does not exist, generate one
  143. newMData, err := generateMetadata(filename, neverExpire, "")
  144. if err != nil {
  145. return metadata, err
  146. }
  147. metadataWrite(filename, &newMData)
  148. b, err = ioutil.ReadFile(path.Join(Config.metaDir, filename))
  149. if err != nil {
  150. return metadata, BadMetadata
  151. }
  152. }
  153. mjson := MetadataJSON{}
  154. err = json.Unmarshal(b, &mjson)
  155. if err != nil {
  156. return metadata, BadMetadata
  157. }
  158. metadata.DeleteKey = mjson.DeleteKey
  159. metadata.Mimetype = mjson.Mimetype
  160. metadata.ArchiveFiles = mjson.ArchiveFiles
  161. metadata.Sha256sum = mjson.Sha256sum
  162. metadata.Expiry = time.Unix(mjson.Expiry, 0)
  163. metadata.Size = mjson.Size
  164. return
  165. }