server/admin/api/file.go

154 lines
3.7 KiB
Go
Raw Normal View History

package api
2016-01-20 21:44:34 +00:00
import (
2016-01-23 11:19:47 +00:00
"bufio"
2016-01-20 21:44:34 +00:00
"crypto/sha512"
"encoding/base32"
2017-01-04 00:30:24 +00:00
"encoding/hex"
2016-01-20 21:44:34 +00:00
"errors"
2016-12-08 11:00:53 +00:00
"fmt"
"log"
2016-01-20 21:44:34 +00:00
"net/http"
"os"
"path"
"strings"
"srs.epita.fr/fic-server/libfic"
)
var CloudDAVBase string
var CloudUsername string
var CloudPassword string
var RapidImport bool
2016-12-08 11:00:53 +00:00
type uploadedFile struct {
URI string
2017-01-04 00:30:24 +00:00
Digest string
2016-12-08 11:00:53 +00:00
Path string
Parts []string
}
2017-01-05 01:21:32 +00:00
func importFile(uf uploadedFile, next func(string, string, []byte) (interface{}, error)) (interface{}, error) {
var hash [sha512.Size]byte
var logStr string
var fromURI string
var getFile func(string) error
if uf.URI != "" && len(uf.Parts) > 0 {
hash = sha512.Sum512([]byte(uf.URI))
logStr = fmt.Sprintf("Import file from Cloud: %s =>", uf.Parts)
fromURI = uf.URI
getFile = func(dest string) error {
if fdto, err := os.Create(dest); err != nil {
return err
} else {
writer := bufio.NewWriter(fdto)
for _, partname := range uf.Parts {
if err := getCloudPart(partname, writer); err != nil {
return err
}
}
fdto.Close()
}
return nil
}
} else if uf.URI != "" {
2016-12-08 11:00:53 +00:00
hash = sha512.Sum512([]byte(uf.URI))
logStr = "Import file from Cloud: " + uf.URI + " =>"
fromURI = uf.URI
getFile = func(dest string) error { return getCloudFile(uf.URI, dest) }
} else if uf.Path != "" && len(uf.Parts) > 0 {
hash = sha512.Sum512([]byte(uf.Path))
logStr = fmt.Sprintf("Import file from local FS: %s =>", uf.Parts)
fromURI = uf.Path
getFile = func(dest string) error {
if fdto, err := os.Create(dest); err != nil {
return err
} else {
writer := bufio.NewWriter(fdto)
for _, partname := range uf.Parts {
if fdfrm, err := os.Open(partname); err != nil {
return err
} else {
reader := bufio.NewReader(fdfrm)
reader.WriteTo(writer)
writer.Flush()
fdfrm.Close()
}
}
fdto.Close()
}
return nil
}
} else if uf.Path != "" {
hash = sha512.Sum512([]byte(uf.Path))
logStr = "Import file from local FS: " + uf.Path + " =>"
fromURI = uf.Path
getFile = func(dest string) error { return os.Symlink(uf.Path, dest) }
} else {
return nil, errors.New("URI or path not filled")
2016-01-20 21:44:34 +00:00
}
pathname := path.Join(fic.FilesDir, strings.ToLower(base32.StdEncoding.EncodeToString(hash[:])), path.Base(fromURI))
2016-01-20 21:44:34 +00:00
// Remove the file if it exists
// TODO: check if this is symlink => remove to avoid File not found error after, because the file is writen at the adresse pointed.
2017-01-05 01:21:32 +00:00
if _, err := os.Stat(pathname); !os.IsNotExist(err) && !RapidImport {
if err := os.Remove(pathname); err != nil {
return nil, err
}
}
if _, err := os.Stat(pathname); os.IsNotExist(err) {
log.Println(logStr, pathname)
2016-01-23 11:19:47 +00:00
if err := os.MkdirAll(path.Dir(pathname), 0777); err != nil {
return nil, err
} else if err := getFile(pathname); err != nil {
2016-01-20 21:44:34 +00:00
return nil, err
}
2016-01-20 21:44:34 +00:00
}
2017-01-04 00:30:24 +00:00
if digest, err := hex.DecodeString(uf.Digest); err != nil {
return nil, err
} else {
2017-01-05 01:21:32 +00:00
return next(pathname, fromURI, digest)
2017-01-04 00:30:24 +00:00
}
2016-01-20 21:44:34 +00:00
}
2016-01-23 12:19:28 +00:00
func getCloudFile(pathname string, dest string) error {
if fd, err := os.Create(dest); err != nil {
return err
} else {
defer fd.Close()
writer := bufio.NewWriter(fd)
if err := getCloudPart(pathname, writer); err != nil {
return err
}
}
return nil
}
func getCloudPart(pathname string, writer *bufio.Writer) error {
2016-01-20 21:44:34 +00:00
client := http.Client{}
if req, err := http.NewRequest("GET", CloudDAVBase+pathname, nil); err != nil {
2016-01-23 11:19:47 +00:00
return err
2016-01-20 21:44:34 +00:00
} else {
req.SetBasicAuth(CloudUsername, CloudPassword)
if resp, err := client.Do(req); err != nil {
2016-01-23 11:19:47 +00:00
return err
2016-01-20 21:44:34 +00:00
} else {
defer resp.Body.Close()
2016-01-23 11:19:47 +00:00
if resp.StatusCode != http.StatusOK {
return errors.New(resp.Status)
2016-01-20 21:44:34 +00:00
} else {
reader := bufio.NewReader(resp.Body)
reader.WriteTo(writer)
writer.Flush()
2016-01-20 21:44:34 +00:00
}
}
}
2016-01-23 11:19:47 +00:00
return nil
2016-01-20 21:44:34 +00:00
}