|
|
package main
import ( "archive/tar" "archive/zip" "compress/bzip2" "compress/gzip" "crypto/sha256" "encoding/hex" "errors" "io" "sort" "time" "unicode"
"github.com/andreimarcu/linx-server/backends" "github.com/andreimarcu/linx-server/expiry" "github.com/dchest/uniuri" "gopkg.in/h2non/filetype.v1" )
var NotFoundErr = errors.New("File not found.")
func generateMetadata(fName string, exp time.Time, delKey string) (m backends.Metadata, err error) { file, err := fileBackend.Open(fName) if err != nil { return } defer file.Close()
m.Size, err = fileBackend.Size(fName) if err != nil { return }
m.Expiry = exp
if delKey == "" { m.DeleteKey = uniuri.NewLen(30) } else { m.DeleteKey = delKey }
// Get first 512 bytes for mimetype detection
header := make([]byte, 512) file.Read(header)
kind, err := filetype.Match(header) if err != nil { m.Mimetype = "application/octet-stream" } else { m.Mimetype = kind.MIME.Value }
if m.Mimetype == "" { // Check if the file seems anything like text
if printable(header) { m.Mimetype = "text/plain" } else { m.Mimetype = "application/octet-stream" } }
// Compute the sha256sum
hasher := sha256.New() file.Seek(0, 0) _, err = io.Copy(hasher, file) if err == nil { m.Sha256sum = hex.EncodeToString(hasher.Sum(nil)) } file.Seek(0, 0)
// If archive, grab list of filenames
if m.Mimetype == "application/x-tar" { tReadr := tar.NewReader(file) for { hdr, err := tReadr.Next() if err == io.EOF || err != nil { break } if hdr.Typeflag == tar.TypeDir || hdr.Typeflag == tar.TypeReg { m.ArchiveFiles = append(m.ArchiveFiles, hdr.Name) } } sort.Strings(m.ArchiveFiles) } else if m.Mimetype == "application/x-gzip" { gzf, err := gzip.NewReader(file) if err == nil { tReadr := tar.NewReader(gzf) for { hdr, err := tReadr.Next() if err == io.EOF || err != nil { break } if hdr.Typeflag == tar.TypeDir || hdr.Typeflag == tar.TypeReg { m.ArchiveFiles = append(m.ArchiveFiles, hdr.Name) } } sort.Strings(m.ArchiveFiles) } } else if m.Mimetype == "application/x-bzip" { bzf := bzip2.NewReader(file) tReadr := tar.NewReader(bzf) for { hdr, err := tReadr.Next() if err == io.EOF || err != nil { break } if hdr.Typeflag == tar.TypeDir || hdr.Typeflag == tar.TypeReg { m.ArchiveFiles = append(m.ArchiveFiles, hdr.Name) } } sort.Strings(m.ArchiveFiles) } else if m.Mimetype == "application/zip" { zf, err := zip.NewReader(file, m.Size) if err == nil { for _, f := range zf.File { m.ArchiveFiles = append(m.ArchiveFiles, f.Name) } } sort.Strings(m.ArchiveFiles) }
return }
func metadataWrite(filename string, metadata *backends.Metadata) error { return metaBackend.Put(filename, metadata) }
func metadataRead(filename string) (metadata backends.Metadata, err error) { metadata, err = metaBackend.Get(filename) if err != nil { // Metadata does not exist, generate one
newMData, err := generateMetadata(filename, expiry.NeverExpire, "") if err != nil { return metadata, err } metadataWrite(filename, &newMData)
metadata, err = metaBackend.Get(filename) }
return }
func printable(data []byte) bool { for i, b := range data { r := rune(b)
// A null terminator that's not at the beginning of the file
if r == 0 && i == 0 { return false } else if r == 0 && i < 0 { continue }
if r > unicode.MaxASCII { return false }
}
return true }
|