andreimarcu
9 years ago
7 changed files with 228 additions and 172 deletions
-
5delete.go
-
117display.go
-
10expiry.go
-
21fileserve.go
-
198meta.go
-
6torrent.go
-
43upload.go
@ -1,84 +1,188 @@ |
|||||
package main |
package main |
||||
|
|
||||
import ( |
import ( |
||||
"bufio" |
|
||||
|
"archive/tar" |
||||
|
"archive/zip" |
||||
|
"compress/bzip2" |
||||
|
"compress/gzip" |
||||
|
"crypto/sha256" |
||||
|
"encoding/hex" |
||||
|
"encoding/json" |
||||
"errors" |
"errors" |
||||
"fmt" |
|
||||
|
"io" |
||||
|
"io/ioutil" |
||||
"os" |
"os" |
||||
"path" |
"path" |
||||
"strconv" |
|
||||
|
"sort" |
||||
"time" |
"time" |
||||
|
|
||||
|
"bitbucket.org/taruti/mimemagic" |
||||
|
"github.com/dchest/uniuri" |
||||
) |
) |
||||
|
|
||||
// Write metadata from Upload struct to file
|
|
||||
func metadataWrite(filename string, upload *Upload) error { |
|
||||
// Write metadata, overwriting if necessary
|
|
||||
|
type MetadataJSON struct { |
||||
|
DeleteKey string `json:"delete_key"` |
||||
|
Sha256sum string `json:"sha256sum"` |
||||
|
Mimetype string `json:"mimetype"` |
||||
|
Size int64 `json:"size"` |
||||
|
Expiry int64 `json:"expiry"` |
||||
|
ArchiveFiles []string `json:"archive_files,omitempty"` |
||||
|
} |
||||
|
|
||||
|
type Metadata struct { |
||||
|
DeleteKey string |
||||
|
Sha256sum string |
||||
|
Mimetype string |
||||
|
Size int64 |
||||
|
Expiry time.Time |
||||
|
ArchiveFiles []string |
||||
|
} |
||||
|
|
||||
|
var NotFoundErr = errors.New("File not found.") |
||||
|
var BadMetadata = errors.New("Corrupted metadata.") |
||||
|
|
||||
file, err := os.Create(path.Join(Config.metaDir, upload.Filename)) |
|
||||
|
func generateMetadata(fName string, exp time.Time, delKey string) (m Metadata, err error) { |
||||
|
file, err := os.Open(path.Join(Config.filesDir, fName)) |
||||
|
fileInfo, err := os.Stat(path.Join(Config.filesDir, fName)) |
||||
if err != nil { |
if err != nil { |
||||
return err |
|
||||
|
return |
||||
} |
} |
||||
|
|
||||
defer file.Close() |
defer file.Close() |
||||
|
|
||||
w := bufio.NewWriter(file) |
|
||||
|
m.Size = fileInfo.Size() |
||||
|
m.Expiry = exp |
||||
|
|
||||
fmt.Fprintln(w, upload.Expiry.Unix()) |
|
||||
fmt.Fprintln(w, upload.DeleteKey) |
|
||||
|
if delKey == "" { |
||||
|
m.DeleteKey = uniuri.NewLen(30) |
||||
|
} else { |
||||
|
m.DeleteKey = delKey |
||||
|
} |
||||
|
|
||||
return w.Flush() |
|
||||
} |
|
||||
|
// Get first 512 bytes for mimetype detection
|
||||
|
header := make([]byte, 512) |
||||
|
file.Read(header) |
||||
|
|
||||
// Return list of strings from a filename's metadata source
|
|
||||
func metadataRead(filename string) ([]string, error) { |
|
||||
file, err := os.Open(path.Join(Config.metaDir, filename)) |
|
||||
|
m.Mimetype = mimemagic.Match("", header) |
||||
|
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
|
// 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)) |
||||
} |
} |
||||
|
|
||||
defer file.Close() |
|
||||
|
|
||||
var lines []string |
|
||||
scanner := bufio.NewScanner(file) |
|
||||
for scanner.Scan() { |
|
||||
lines = append(lines, scanner.Text()) |
|
||||
|
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 lines, scanner.Err() |
|
||||
|
return |
||||
} |
} |
||||
|
|
||||
func metadataGetExpiry(filename string) (expiry time.Time, err error) { |
|
||||
metadata, err := metadataRead(filename) |
|
||||
|
func metadataWrite(filename string, metadata *Metadata) error { |
||||
|
file, err := os.Create(path.Join(Config.metaDir, filename)) |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
defer file.Close() |
||||
|
|
||||
// XXX in this case it's up to the caller to determine proper behavior
|
|
||||
// for a nonexistant metadata file or broken file
|
|
||||
|
mjson := MetadataJSON{} |
||||
|
mjson.DeleteKey = metadata.DeleteKey |
||||
|
mjson.Mimetype = metadata.Mimetype |
||||
|
mjson.ArchiveFiles = metadata.ArchiveFiles |
||||
|
mjson.Sha256sum = metadata.Sha256sum |
||||
|
mjson.Expiry = metadata.Expiry.Unix() |
||||
|
mjson.Size = metadata.Size |
||||
|
|
||||
|
byt, err := json.Marshal(mjson) |
||||
if err != nil { |
if err != nil { |
||||
return |
|
||||
|
return err |
||||
} |
} |
||||
|
|
||||
if len(metadata) < 1 { |
|
||||
err = errors.New("ERR: Metadata file does not contain expiry") |
|
||||
return |
|
||||
|
_, err = file.Write(byt) |
||||
|
if err != nil { |
||||
|
return err |
||||
} |
} |
||||
|
|
||||
expirySecs, err := strconv.ParseInt(metadata[0], 10, 64) |
|
||||
expiry = time.Unix(expirySecs, 0) |
|
||||
return |
|
||||
|
return nil |
||||
} |
} |
||||
|
|
||||
func metadataGetDeleteKey(filename string) (string, error) { |
|
||||
metadata, err := metadataRead(filename) |
|
||||
|
|
||||
if len(metadata) < 2 { |
|
||||
err := errors.New("ERR: Metadata file does not contain deletion key") |
|
||||
return "", err |
|
||||
|
func metadataRead(filename string) (metadata Metadata, err error) { |
||||
|
b, err := ioutil.ReadFile(path.Join(Config.metaDir, filename)) |
||||
|
if err != nil { |
||||
|
// Metadata does not exist, generate one
|
||||
|
newMData, err := generateMetadata(filename, neverExpire, "") |
||||
|
if err != nil { |
||||
|
return metadata, err |
||||
|
} |
||||
|
metadataWrite(filename, &newMData) |
||||
|
b, err = ioutil.ReadFile(path.Join(Config.metaDir, filename)) |
||||
|
if err != nil { |
||||
|
return metadata, BadMetadata |
||||
|
} |
||||
} |
} |
||||
|
|
||||
|
mjson := MetadataJSON{} |
||||
|
|
||||
|
err = json.Unmarshal(b, &mjson) |
||||
if err != nil { |
if err != nil { |
||||
return "", err |
|
||||
} else { |
|
||||
return metadata[1], err |
|
||||
|
return metadata, BadMetadata |
||||
} |
} |
||||
|
|
||||
|
metadata.DeleteKey = mjson.DeleteKey |
||||
|
metadata.Mimetype = mjson.Mimetype |
||||
|
metadata.ArchiveFiles = mjson.ArchiveFiles |
||||
|
metadata.Sha256sum = mjson.Sha256sum |
||||
|
metadata.Expiry = time.Unix(mjson.Expiry, 0) |
||||
|
metadata.Size = mjson.Size |
||||
|
|
||||
|
return |
||||
} |
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue